单例 httpClient 到 AppService 的单个实例

Posted

技术标签:

【中文标题】单例 httpClient 到 AppService 的单个实例【英文标题】:Singleton httpClient to single Instance of AppService 【发布时间】:2021-02-22 13:08:38 【问题描述】:

首先对不起我糟糕的英语:'(。

我正在开发一个客户端以将 POST 消息发送到托管在 Azure AppService 中的 WebAPI。我读到的最佳实践是使用单例模式,所以我是这样开发的。

公共静态类 UtilHTTP

    private static readonly ConcurrentDictionary<string, HttpClient> dicClient = new ConcurrentDictionary<string, HttpClient>();

    public static string PostSingleton(string url, string contentType, string accept, string rq, Dictionary<string, string> headers)
    
        Task<string> response = Fetch(url, contentType, accept, rq, headers);
        response.Wait();
        return response.Result;
    

    private static HttpClient GetdicClient(string url, string contentType, string accept)
    
        string key = string.Format("0#1#2", url, contentType, accept);
        if (!dicClient.ContainsKey(key))
        
            dicClient.GetOrAdd(key, new HttpClient());

            if (!string.IsNullOrEmpty(accept))
            
                dicClient[key].DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue(accept));
            
        
        return dicClient[key];
    

    private static async Task<string> Fetch(string url, string contentType, string accept, string rq, Dictionary<string, string> headers)
    
        //_http.Timeout = new TimeSpan(0,0,6);
        HttpContent content;
        if (string.IsNullOrEmpty(contentType))
        
            content = new StringContent(rq, Encoding.UTF8);
        
        else
        
            content = new StringContent(rq, Encoding.UTF8, contentType);
        

        if (headers != null)
        
            foreach (KeyValuePair<string, string> h in headers)
            
                content.Headers.Add(h.Key, h.Value);
            
        

        HttpResponseMessage response = await GetdicClient(url, contentType, accept).PostAsync(url, content);
        string resultContent = await response.Content.ReadAsStringAsync();

        if (!response.IsSuccessStatusCode)
        
            resultContent = response.ReasonPhrase;
        

        return resultContent;
    


我在 AppService 中有两个服务实例,但是所有请求都发往同一个实例,所以我无法扩展服务,性能也不是很好。

Insights Performance

代码有问题吗?你认为是服务器端的问题吗?我必须使用其他模式吗?

非常感谢!

【问题讨论】:

【参考方案1】:

乍一看,您正在正确地执行单例HttpClient(每个客户端)。我能看到的唯一问题是,如果您对同一个 URL 进行多次调用,并且在 URL 中使用不同的参数,这些参数将导致创建一个新的客户端。不过,我不知道您正在这样做,所以这里可能没有问题。

您讨论的另一个问题(关于所有请求都发送到您的应用服务的同一实例)可能与 ARR 亲和性(所谓的“粘性会话”)有关。检查您的应用服务设置(配置 -> 常规设置)确保它已关闭:

【讨论】:

没错。而已!!!非常感谢!让我知道我可以在哪里给你发一份鳄梨酱:)

以上是关于单例 httpClient 到 AppService 的单个实例的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET MVC 中的 HttpClient 单例实现

是单例 HttpClient X 分钟后接收新的 HttpMessageHandler

突然无法更改 HttpClient 上的超时

1. 单例模式

Ktor 的 HttpClient 使用的正确模式

如何避免 .NET 中 HttpClient 的 DNS 失效问题?