2016-05-26 5 views
2

In den letzten paar Wochen haben wir diese Fehlermeldung bei der Verwendung des Azure Search SDK (1.1.1 - 1.1.2) und bei Suchvorgängen erhalten .Normalerweise ist nur eine Verwendung jeder Socket-Adresse (Protokoll/Netzwerkadresse/Port) zulässig

Wir verwenden das Such-SDK über interne APIs (bereitgestellt als Azure Web Apps), die basierend auf Datenverkehr aufsteigend skaliert werden (sodass mehr als eine Instanz der APIs die Suchvorgänge durchführen kann).

Unsere API 5 verschiedene Indizes abfragt und unterhält eine im Speicher befindliche Kopie des SearchIndexClient Objekt, das zu jedem Index entspricht, eine sehr einfache Implementierung würde wie folgt aussehen:

public class AzureSearchService 
{ 
    private readonly SearchServiceClient _serviceClient; 

    private Dictionary<string, SearchIndexClient> _clientDictionary; 

    public AzureSearchService() 
    { 
     _serviceClient = new SearchServiceClient("myservicename", new SearchCredentials("myservicekey")); 
     _clientDictionary = new Dictionary<string, SearchIndexClient>(); 
    } 

    public SearchIndexClient GetClient(string indexName) 
    { 
     try 
     { 
      if (!_clientDictionary.ContainsKey(indexName)) 
      { 
       _clientDictionary.Add(indexName, _serviceClient.Indexes.GetClient(indexName)); 
      } 
      return _clientDictionary[indexName]; 
     } 
     catch 
     { 
      return null; 
     } 
    } 

    public async Task<SearchResults> SearchIndex(SearchIndexClient client, string text) 
    { 
     var parameters = new SearchParameters(); 
     parameters.Top = 10; 
     parameters.IncludeTotalResultCount = true; 
     var response = await client.Documents.SearchWithHttpMessagesAsync(text, parameters, null, null); 
     return response.Body; 
    } 
} 

Und die API würde den Dienst aufrufen, indem :

public class SearchController : ApiController 
{ 
     private readonly AzureSearchService service; 

     public SearchController() 
     { 
      service = new AzureSearchService(); 
     } 


     public async Task<HttpResponseMessage> Post(string indexName, [FromBody] string text) 
     { 
      var indexClient = service.GetClient(indexName); 
      var results = await service.SearchIndex(indexClient, text); 
      return Request.CreateResponse(HttpStatusCode.OK, results, Configuration.Formatters.JsonFormatter);    
     } 

} 

Wir SearchWithHttpMessagesAsync aufgrund einer Anforderung werden mithilfe von benutzerdefinierten HTTP-Header anstelle der SearchAsync Methode erhalten.

Auf diese Weise vermeiden wir das Öffnen/Schließen des Clients unter Verkehrsstößen. Bevor wir diesen Speichercache verwenden (und jeden Client in eine using-Klausel verpacken), erhalten wir Port-Erschöpfungswarnungen für Azure App Services.

Ist das ein gutes Muster? Könnten wir diesen Fehler erhalten, weil mehrere Instanzen gleichzeitig ausgeführt werden?

Falls es erforderlich ist, zeigt die Stack-Trace:

System.Net.Http.HttpRequestException: Only one usage of each socket address (protocol/network address/port) is normally permitted service.ip.address.hidden:443 


[SocketException:Only one usage of each socket address (protocol/network address/port)is normally permitted service.ip.address.hidden:443] 

at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult) 

at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure,Socket s4,Socket s6,Socket& socket,IPAddress& address,ConnectSocketState state,IAsyncResult asyncResult,Exception& exception) 



[WebException:Unable to connect to the remote server] 

at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult,TransportContext& context) 

at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar) 

EDIT: Wir sind auch erhalten diesen Fehler A connection attempt failed because the connected party did not properly respond after a period of time:

System.Net.Http.HttpRequestException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond service.ip.address.hidden:443 


[SocketException:A connection attempt failed because the connected party did not properly respond after a period of time,or established connection failed because connected host has failed to respond service.ip.address.hidden:443] 

at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult) 

at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure,Socket s4,Socket s6,Socket& socket,IPAddress& address,ConnectSocketState state,IAsyncResult asyncResult,Exception& exception) 



[WebException:Unable to connect to the remote server] 

at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult,TransportContext& context) 

at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar) 
+0

Nur um zu klären - Ist die Fehlermeldung über "nur eine Verwendung jeder Socket-Adresse" mit oder ohne den Cache von SearchIndexClients passiert? –

+0

Hallo Bruce. Die Nachricht befindet sich im Cache. –

+0

Danke für die Klarstellung. Ich habe meine Antwort gepostet. Wenn der Fehler "Verbindungsversuch fehlgeschlagen" weiterhin besteht, wenden Sie sich bitte direkt an mich, da dies möglicherweise ein anderes Problem mit der Verfügbarkeit Ihres Dienstes darstellt. –

Antwort

1

Wie im Code implementiert, um Ihre Frage, der Cache wird Port Erschöpfung nicht verhindern. Dies liegt daran, dass Sie es als ein Feld der ApiController instanziieren, das einmal pro Anforderung erstellt wird. Wenn Sie die Port-Erschöpfung vermeiden möchten, muss der Cache für alle Anfragen freigegeben werden. Um es nebenläufigkeits-sicher zu machen, sollten Sie etwas wie ConcurrentDictionary anstelle von Dictionary verwenden.

Der Fehler "Verbindungsversuch fehlgeschlagen" ist wahrscheinlich nicht relevant.

+0

Danke Bruce, ich werde dann daran arbeiten. Denkst du, dass das Erstellen des Service als eine statische auch die gleiche Wirkung haben wird? –

+0

Bruce, ich habe das Singleton-Muster auf dem Dienst implementiert und das scheint das Problem bisher gelöst zu haben, ich werde es weiter beobachten, nur für den Fall, aber markiert deine Antwort :) –

Verwandte Themen