我注意到在修改 HttpClient.DefaultRequestHeaders 时,使用HttpClient是不是线程安全的,但是我想发出尽可能多的请求。 每个请求我都需要一个自定义标头(其他2个标头始终相同)。网址也有所变化
当前,我正在为每个请求创建一个新的HttpClient,但我觉得创建10k + HttpClients不是这里的最佳选择。
我想用2个DefaultRequestHeaders制作一个静态HttpClient,并将此HttpClient用于每个请求,但还要添加一个自定义标头。
我想尽快解决这个问题,所以如果您有其他疑问,我会接受。
Parallel.ForEach(Requests, Request =>
{
var Client = new HttpClient();
Client.DefaultRequestHeaders.Clear();
Client.DefaultRequestHeaders.Add("Header1", "Value1");
Client.DefaultRequestHeaders.Add("Header2", "Value2");
Client.DefaultRequestHeaders.Add("Header3", "Value for exact this request");
var response = Client.PutAsync(new Uri($"http://example.com/books/1234/readers/837"), null); //.Result (?)
Client.Dispose();
});
答案 0 :(得分:0)
从.NET Core 2.1开始使用HttpClient的标准方案是:
直接传递所有标头且不进行批处理的直接示例:
var tasks = Enumerable.Range(1, 10000)
.Select(v => HttpClientFactory.Create().SendAsync(new HttpRequestMessage(HttpMethod.Put, new Uri($"http://example.com/books/1234/readers/837"))
{
Headers =
{
{"Header1", "Value1"},
{"Header2", "Value2"},
{"Header3", v.ToString()},
},
Content = new StringContent("{test:\"hello\"}", Encoding.UTF8, "application/json")
}));
var responses = await Task.WhenAll(tasks).ConfigureAwait(false);
// ..
备注:
答案 1 :(得分:0)
我认为DelegatingHandler
的使用将能够完成您所需要的。您将停止使用DefaultRequestHeaders,而是在DelegatingHandler
中进行设置。
还请注意,HttpClient
对于请求是线程安全的,不应丢弃。这是因为它处理了底层HttpMessageHandler
,而底层Sample.cs
会导致较低级别的效率低下。更多详细信息,请参见http://www.nimaara.com/2016/11/01/beware-of-the-net-httpclient/。
// .Net Framework, careful here because the sockets will be cached, network changes will break your app
// see http://www.nimaara.com/2016/11/01/beware-of-the-net-httpclient/ for more details
var client = new HttpClient(new MyCustomHandler() { InnerHandler = new HttpClientHandler() });
// .Net Core
client = new HttpClient(new MyCustomHandler() { InnerHandler = new SocketsHttpHandler() { PooledConnectionLifetime = TimeSpan.FromMinutes(1) } });
Parallel.ForEach(Requests, Request =>
{
var response = client.PutAsync(new Uri($"http://example.com/books/1234/readers/837"), null); //.Result (?)
// do not dispose of httpclient!
});
MyCustomHandler.cs
public class MyCustomHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// the static headers
request.Headers.Add("Header1", "Value1");
request.Headers.Add("Header2", "Value2");
// the unique header
SignRequest(request);
return base.SendAsync(request, cancellationToken);
}
public void SignRequest(HttpRequestMessage message)
{
// usually the pattern of a unique header per request is for an authorization header based on some signature of the request
// this logic would be here
// generate the signature
string signature = new Random().Next(int.MaxValue).ToString();
message.Headers.Add("Header3", signature);
}
}
{{1}}
答案 2 :(得分:0)
不要将DefaultRequestHeaders
用于不适用于HttpClient
发送的 all 请求的标头。
此外,请勿为每个请求创建一个HttpClient
。
您可以轻松地做到这一点,而不是为每个请求创建一个HttpRequestMessage
,将所需的标头应用到其中,并在整个HttpClient
中使用相同的.SendAsync()
:
using (var request = new HttpRequestMessage(HttpMethod.Put, url)
{
request.Headers.<add here>;
// optionally set .Content
using (var response = await httpClient.SendAsync(request))
{
// ... process response
}
}