通常只允许使用每个套接字地址(协议/网络地址/端口)

时间:2016-05-26 19:46:55

标签: azure-search

过去几周,我们在使用Azure Search SDK(1.1.1 - 1.1.2)并执行搜索时遇到此错误消息。

我们使用内部API(部署为Azure Web Apps)的Search SDK,它根据流量向上扩展(因此可能有超过1个API实例进行搜索)。

我们的API查询5个不同的索引,并维护与每个索引对应的SearchIndexClient对象的内存中副本,一个非常简单的实现看起来像:

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

API将通过以下方式调用服务:

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

}

由于要求接收自定义HTTP标头而不是SearchWithHttpMessagesAsync方法,我们正在使用SearchAsync

这样我们就可以避免在流量突发下打开/关闭客户端。在使用此内存缓存(并将每个客户端包装在using子句上)之前,我们将在Azure应用服务上获得端口耗尽警报。

这是一个好模式吗?我们可能因为多个实例并行运行而收到此错误吗?

如果需要,堆栈跟踪显示:

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)

编辑:我们收到此错误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)

1 个答案:

答案 0 :(得分:2)

正如您问题中的代码所实现的那样,缓存不会阻止端口耗尽。这是因为您将其实例化为ApiController的字段,每个请求创建一次。{1}}。如果要避免端口耗尽,则必须在所有请求之间共享缓存。为了使其兼容并发,您应该使用ConcurrentDictionary而不是Dictionary之类的内容。

&#34;连接尝试失败&#34;错误很可能无关。