首页 > 解决方案 > 正确使用 IHttpClientFactory 进行 .net-core 瞬态服务

问题描述

我正在研究使用 IHttpClientFactory 在我的 asp.net 核心应用程序中调用外部 API。我见过一些例子,其中客户端工厂是在服务类的构造函数中创建的。然后那个类的方法,调用那个客户端工厂来生成一个 HttpClient 的实例来发出 Http 请求。像下面的示例代码:

public class MyTransientService: IMyService
{
    private readonly IHttpClientFactory _clientFactory;

    public MyTransientService(
        IHttpClientFactory clientFactory
    )
    {
        _clientFactory = clientFactory;
    }

    public async Task<MyData> GetData()
    {
        //construct the request
        var httpClient = _clientFactory.CreateClient();
        var response = await client.SendAsync(request);
        ...
    }
}

如果service在startup.cs中注册为transient,是不是每次调用service都会生成一个新的HttpClientFactory实例?每个请求一个新的 HttpClientFactory?那么以下不是更有效的使用工厂的方法吗?

public class MyTransientService: IMyService
    {
        private readonly HttpClient _client;
    
        public MyTransientService(
            HtpClient client
        )
        {
            _client = client;
        }
    
        public async Task<MyData> GetData()
        {
            Uri uri = new Uri(StaticUtils.AddQueryString(url, props));
            var response = await _client.SendAsync(request);
            ...
        }
    }

标签: c#asp.net-coredotnet-httpclient

解决方案


我会考虑自己创建 HttpClient 是不好的做法,因为您可以控制创建的数量。如果MyTransientService是瞬态的,您最终会创建许多套接字连接(每个实例/请求一个)HttpClient以供重用。

看看 Typed 客户端:https ://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient("hello", c =>
    {
        c.BaseAddress = new Uri("http://localhost:5000");
    })
    .AddTypedClient<MyTransientService>();

    services.AddControllers();
}

public class MyTransientService: IMyService
{
    private readonly HttpClient _client;

    public MyTransientService(
        HtpClient client
    )
    {
        _client = client;
    }

    public async Task<MyData> GetData()
    {
        Uri uri = new Uri(StaticUtils.AddQueryString(url, props));
        var response = await _client.SendAsync(request);
        ...
    }
}

推荐阅读