我遇到了一个问题,但还没有找到答案。
简而言之,我们制作了一个类型化的
HttpClient
并将其注入到单例服务中。一切似乎都很顺利。
现在我们在内部调用此服务
BackgroundService
并且那里有 10 个并行调用 _testService.GetData();
- 前 10 个工作正常,接下来的请求已经卡住并超时。生命周期的某些东西似乎不对。
当客户端第二次被重用时,问题就出现了。客户端似乎是暂时的,但服务现在将是单例的
services.AddHttpClient<ITestClient, TestClient>(client =>
{
client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// base address
});
public class TestService : ITestService
{
private readonly ITestClient _client;
private readonly ISettings _settings;
private readonly ILogger _logger;
public NrdClient(
ITestClient client,
ISettings settings,
ILogger logger)
{
ArgumentNullException.ThrowIfNull(client);
_client = client;
ArgumentNullException.ThrowIfNull(settings);
_settings = settings;
ArgumentNullException.ThrowIfNull(logger);
_logger = logger;
}
public async Task<Dto> GetData()
{
try
{
var content = new StringContent(postData, Encoding.UTF8, "application/x-www-form-urlencoded");
var response = await _client.PostAsync<T>(url, content);
return response;
}
catch (Exception ex)
{
throw;
}
}
}
public class TestClient : ITestClient
{
private readonly HttpClient _client;
public TestClient()
{
}
public TestClient(HttpClient httpClient, ISettings settings)
{
ArgumentNullException.ThrowIfNull(httpClient);
ArgumentNullException.ThrowIfNull(settings);
_client = httpClient;
_client.Timeout = new TimeSpan(0, 0, 10);
}
public async virtual Task<T> PostAsync<T>(string requestUrl, HttpContent content)
{
var response = await _client.PostAsync(requestUrl, content);
using var stream = await response.Content.ReadAsStreamAsync();
using GZipStream decompressed = new(stream, CompressionMode.Decompress);
using StreamReader reader = new(decompressed);
using JsonTextReader jsonTextReader = new(reader);
return new JsonSerializer().Deserialize<T>(jsonTextReader);
}
}
如果您的客户端作为瞬态注入到单例类实例中,它实际上会成为单例本身,这也可能导致一些问题,这里有很好的描述:https://learn.microsoft.com/en-us/ dotnet/fundamentals/networking/http/httpclient-guidelines#dns-behavior
我认为根据 Microsoft 的说法,您应该使用以下内容: https://learn.microsoft.com/en-us/dotnet/fundamentals/networking/http/httpclient-guidelines#pooled-connections
好的做法是为您的
BaseAddress
设置 Httpclient
,这可能也适用于您的用例。