Usually only one use of each socket address is allowed (protocol / network address / port)

Over the past few weeks, we have encountered this error message while using the Azure Search SDK (1.1.1 - 1.1.2) and performing searches.

We use the search SDK from internal APIs (deployed as Azure Web Apps) that scale up traffic (so there may be more than one API instance doing the search).

Our API requests 5 different indexes and maintains an in-memory copy of the SearchIndexClient object corresponding to each index, a very simple implementation would look like this:

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;
    }
}

      

And the API will reference the service:

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);              
        }

}

      

We are using SearchWithHttpMessagesAsync

because of the requirement to receive custom HTTP headers instead of the method SearchAsync

.

Thus, we avoid opening / closing the client in traffic packets. Before we use this memory cache (and wrap each client in a proposal using

), we'll get port exhaustion alerts in Azure App Services.

Is this a good example? Could we get this error due to multiple instances running in parallel?

If necessary, the stack trace shows:

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 . We also get this error 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)

      

+2


source to share


1 answer


As implemented in the code in your question, the cache will not prevent the port from being exhausted. This is because you are creating it as a field ApiController

that is created once per request. If you want to avoid port exhaustion, the cache must be shared across all requests. To make it concurrency -safe you should use something like ConcurrentDictionary

instead Dictionary

.



There is no connection attempt error.

+2


source







All Articles