ASP.net HttpRequest上的静态HttpClient线程安全

sad*_*t75 7 asp.net httprequest static-libraries thread-safety dotnet-httpclient

我们正在为HttpClient创建一个包装器.我们将遵循https://github.com/mspnp/performance-optimization的性能优化指南.我们希望避免反模式 - 该文档中提到的不正确的实例化.我将此指南提交给我的团队使用静态HttpClient.我得到的反馈是线程安全性.每个请求都有一个包含用户声明的标头.由于我有一个静态的HttpClient,它是否是线程安全的?如果我们同时有多个请求命中代码(例如GET),那么设置标题是否会出现竞争条件?我们的实施如下.

public class HttpClientHelper{
private static readonly HttpClient _HttpClient;
static HttpClientHelper() {
        HttpClient = new HttpClient();
        HttpClient.Timeout = TimeSpan.FromMinutes(SOME_CONFIG_VALUE);
}

public async Task<HttpResponseMessage> CallHttpClientPostAsync(string requestUri, HttpContent requestBody)
{
    AddHttpRequestHeader(httpClient);
    var response = await httpClient.PostAsync(requestUri, requestBody); //Potential thread synchronization issue???
    return response;
}

public HttpResponseMessage CallHttpClientGet(string requestUri)
{
    AddHttpRequestHeader(httpClient);
    var response = httpClient.GetAsync(requestUri).Result; //Potential thread synchronization issue???
    return response;
}

private void AddHttpRequestHeader(HttpClient client)
{
    string HeaderName = "CorrelationId";
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(Properties.Settings.Default.HttpClientAuthHeaderScheme, GetTokenFromClaims()); //Race condition???
    if (client.DefaultRequestHeaders.Contains(HeaderName))
        client.DefaultRequestHeaders.Remove(HeaderName);
    client.DefaultRequestHeaders.Add(HeaderName, Trace.CorrelationManager.ActivityId.ToString());
}
Run Code Online (Sandbox Code Playgroud)

}

Tod*_*ier 11

你的团队是正确的,这远非线程安全.考虑这种情况:

  • 线程A将CorrelationId标头设置为"foo".
  • 线程B将CorrelationId标头设置为"bar".
  • 线程A发送请求,其中包含线程B的CorrelationId.

一种更好的方法是让您的CallXXX方法创建新的HttpRequestMessage对象,并在这些对象上设置标头,并使用HttpClient.SendAsync进行调用.

请记住,重复使用HttpClient实例仅在您对同一主机进行多次调用时才有用.

  • @OhadSchneider它基于[Daryl Miller的建议](/sf/answers/1579295791/),为你连接的每个不同的API使用一个实例.原因是性能优势(不必打开新连接等)仅与每个主机相关,某些HttpClient属性(如DefatultHeaders)也是如此.然而,现在着名的[套接字问题](https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/)可能会改变我的建议.Windows可以在TIME_WAIT中回收套接字以与其他主机一起使用吗?我不确定.我在那篇文章上发布了这个问题. (2认同)