HttpClientFactory

时间:2019-09-02 16:05:11

标签: c# azure asp.net-core httpclient httpclientfactory

我在Azure上有一个长时间运行的触发式Webjob,它使用多个类型的http客户端来访问远程服务。每次启动的请求数量多达数百万,但是在大约3万之后,我得到了以下异常:

  

System.Net.Http.HttpRequestException:无法对套接字执行操作,因为系统缺少足够的缓冲区空间或队列已满。

我正在使用Microsoft.Extensions.Http 2.2.0通过Http Client Factory注入类型化的HTTP客户端。

现在,我已经尝试使用伪造的数据和接收器在本地运行它;并使用

监控连接
  

netstat -b

...和

  

var ipProperties = IPGlobalProperties.GetIPGlobalProperties();

     

var tcpConnections = ipProperties.GetActiveTcpConnections();

...但是我无法重现该错误;连接的数量始终保持不变。这使我认为连接限制之外的其他原因都会导致此错误。

我会在Azure中尝试相同的方法;但这似乎不起作用,因为Kudu不允许netstat或类似命令。

将客户端添加到这样的服务中:

collection.AddHttpClient<ISenderClient, SenderClient>()
                .ConfigureHttpClient((provider, client) =>
            {
                 //... configuring base url and headers
            })
                .SetHandlerLifetime(TimeSpan.FromMinutes(1));

然后将其注入SenderClient:

public sealed class SenderClient : ISenderClient, IDisposable
    {
        private readonly HttpClient _httpClient;

        public SenderClient(HttpClient httpClient)
        {
            _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
        }

        public void Dispose()
        {
            _httpClient?.Dispose();
        }
    }

SenderClient本身是从服务提供商处检索的:

_client = _provider.GetService<ISenderClient>();

...然后在Parallel.ForEach循环中用于分发http请求:

Parallel.ForEach(batches, new ParallelOptions { MaxDegreeOfParallelism = 8 }, (batch, state, i) =>
            {
                using (var scope = _provider.CreateScope())
                {
                    var provider = scope.ServiceProvider;

                    //... dto mapping

                    var response = _client.SendAsync<Request, Response>(request).GetAwaiter().GetResult();
                 }
             }

SendAsync在哪里

public async Task<TResponse> SendAsync<TRequest, TResponse>(TRequest request)
        {
            var json = JsonConvert.SerializeObject(request);
            using (var content = new StringContent(json, Encoding.UTF8, "application/json"))
            using (var response = await _client.PostAsync(_url, content))
            {
                var responseString = await response.Content.ReadAsStringAsync();
                return JsonConvert.DeserializeObject<TResponse>(responseString);
            }
        }

任何人都可以解释一下导致此异常的原因吗,因为到目前为止,我一直很努力地尝试解决此问题。.

编辑:我认为我的问题不是this post的重复,因为我使用的是HttpClientFactory而不是手动处理客户端。这应注意管理,刷新和处置连接;并且被认为是处理HTTP客户端的首选方式。

在这种情况下,我应该只在一定时间内拥有一个类型的连接。

1 个答案:

答案 0 :(得分:0)

我们将工作转移到具有更高定价层的应用程序服务中,从而解决了该问题;尽管我对这种解决方案并不完全满意。