简体   繁体   English

在 C# 中,如何将 HttpClient 重用于多个服务?

[英]In C#, How can I reuse an HttpClient for multiple services?

I've created a C# microservice which offers several different (but related) functions.我创建了一个 C# 微服务,它提供了几个不同(但相关)的功能。

I am now creating a C# Nuget package for a client which will help other C# microservices to leverage this microservice.我现在正在为一个客户端创建一个 C# Nuget package,这将帮助其他 ZD7EFA19FBE24D3972FDD2D8Z 微服务利用这个微服务。 This will include a Service Collection Extension class to facilitate adding the client to those microservices.这将包括一个服务集合扩展 class,以方便将客户端添加到这些微服务。

In the interest of separating concerns, within the client, I've separated the functionality into three classes:为了分离关注点,在客户端中,我将功能分为三类:

  • SalesforceCacheQuerier SalesforceCacheQuerier
  • SalesforceCacheSyncDataManipulator SalesforceCacheSyncDataManipulator
  • SalesforceCacheAsyncDataManipulator SalesforceCacheAsyncDataManipulator

Each of these need to call out to the same server.这些中的每一个都需要调用同一台服务器。

As a niave first implementation, I've composed this method:作为一个幼稚的第一个实现,我编写了这个方法:

        public static IServiceCollection AddSalesforceClients(this IServiceCollection services)
        {
            services.AddTransient<SalesforceCacheAuthenticationHandler>();
            ConfigureClient(services.AddHttpClient<ISalesforceCacheQuerier, SalesforceCacheQuerier>());
            ConfigureClient(services.AddHttpClient<ISalesforceCacheSyncDataManipulator, SalesforceCacheSyncDataManipulator>());
            ConfigureClient(services.AddHttpClient<ISalesforceCacheAsyncDataManipulator, SalesforceCacheAsyncDataManipulator>());
            return services;
        }

        private static IHttpClientBuilder? ConfigureClient(IHttpClientBuilder? clientBuilder)
            => clientBuilder.ConfigureHttpClient(ConfigureClient)
            .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler())
            .AddHttpMessageHandler<SalesforceCacheAuthenticationHandler>();

        private static void ConfigureClient(IServiceProvider provider, HttpClient client)
        {
            SalesforceCacheSettings? settings = provider.GetRequiredService<SalesforceCacheSettings>();
            client.BaseAddress = new Uri(settings.BaseUrl, settings.ApiEndpoint);
            client.DefaultRequestHeaders.ExpectContinue = true;
        }

However, this generates three separate HttpClients and triples the traffic for the "Identity Server" used to provide Jwt tokens.但是,这会生成三个单独的 HttpClient,并将用于提供 Jwt 令牌的“身份服务器”的流量增加三倍。

How can I refactor this to create and reuse only a single HttpClient?如何重构它以仅创建和重用一个 HttpClient?

You can use HttpClientFactory and inject it in ConfigureServices something like services.AddHttpClient();您可以使用 HttpClientFactory 并将其注入到ConfigureServices中,例如services.AddHttpClient(); Later wherever you need client object just give IHttpClientFactory httpClientFactory in the constructor and you can have access to client object by just asking the factory to create a client.稍后,无论您需要客户端 object,只需在构造函数中提供IHttpClientFactory httpClientFactory ,您就可以通过要求工厂创建客户端来访问客户端 object。

HttpClient = HttpClientFactory.CreateClient(); in this fashion.以这种方式。

In case if you want to hold the authentication for the clients and reuse it.如果您想为客户端保留身份验证并重用它。 I would suggest to maintain a dictionary for each request type.我建议为每种请求类型维护一个字典。

var HttpClients = new Dictionary<string, HttpClient>();

HttpClients.Add(SalesforceCacheQuerierKey, SalesforceCacheQuerierClient);

//assuming all the auth related headers are added to this client object //SalesforceCacheQuerierClient //假设所有与身份验证相关的标头都添加到此客户端 object //SalesforceCacheQuerierClient

and pass these from startup level.并从启动级别传递这些。

What I needed was something like this:我需要的是这样的:

            services.AddHttpClient(SALESFORCE_CACHE_CLIENT, (provider, client) =>
            {
                SalesforceCacheClientSettings? settings = provider.GetRequiredService<SalesforceCacheClientSettings>();
                client.BaseAddress = new Uri(settings.BaseUrl, settings.ApiEndpoint);
                client.DefaultRequestHeaders.ExpectContinue = true;
            })
                .AddHttpMessageHandler<SalesforceCacheAuthenticationHandler>();

            services.AddHttpClient<ISalesforceCacheQuerier, SalesforceCacheQuerier>(SALESFORCE_CACHE_CLIENT);
            services.AddHttpClient<ISalesforceCacheSyncDataManipulator, SalesforceCacheSyncDataManipulator>(SALESFORCE_CACHE_CLIENT);
            services.AddHttpClient<ISalesforceCacheAsyncDataManipulator, SalesforceCacheAsyncDataManipulator>(SALESFORCE_CACHE_CLIENT);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM