"An operation on a socket could not be performed" 与 HttpClientFactory
"An operation on a socket could not be performed" with HttpClientFactory
我在 Azure 上有一个长时间 运行 触发的网络作业,它使用多种类型的 http 客户端来访问远程服务。每次启动的请求量高达数百万,但在 ~30k 之后我收到以下异常:
System.Net.Http.HttpRequestException: An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.
我正在使用 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 客户端的首选方式。
使用这种方法,我应该在特定时间段内只有一个类型的连接。
我们将作业转移到具有更高定价层的应用程序服务,这在某种程度上解决了问题;虽然我对这个解决方案并不完全满意。
我在 Azure 上有一个长时间 运行 触发的网络作业,它使用多种类型的 http 客户端来访问远程服务。每次启动的请求量高达数百万,但在 ~30k 之后我收到以下异常:
System.Net.Http.HttpRequestException: An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.
我正在使用 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 客户端的首选方式。
使用这种方法,我应该在特定时间段内只有一个类型的连接。
我们将作业转移到具有更高定价层的应用程序服务,这在某种程度上解决了问题;虽然我对这个解决方案并不完全满意。