C# 由HttpClientFactory创建的长寿命HttpClient

C# 由HttpClientFactory创建的长寿命HttpClient,c#,asp.net-core,httpclient,object-lifetime,httpclientfactory,C#,Asp.net Core,Httpclient,Object Lifetime,Httpclientfactory,我读过HttpMessageHandlers每2分钟循环一次,但我不确定是否为现有的HttpClient分配了一个新的处理程序 我已经使用SetHandlerLifetime(TimeSpan.FromSeconds(5))对其进行了测试即使经过2分钟的无数请求,httpClient仍能继续工作,这是一个好迹象吗 这是否意味着我没有理由担心DNS更改/套接字耗尽 内部配置服务方法: var myOptions = app.ApplicationServices.GetService<IOp

我读过
HttpMessageHandlers
每2分钟循环一次,但我不确定是否为现有的
HttpClient
分配了一个新的处理程序

我已经使用
SetHandlerLifetime(TimeSpan.FromSeconds(5))对其进行了测试
即使经过2分钟的无数请求,httpClient仍能继续工作,这是一个好迹象吗

这是否意味着我没有理由担心DNS更改/套接字耗尽

内部配置服务方法:

var myOptions = app.ApplicationServices.GetService<IOptionsMonitor<MyOptions>>();
HttpClient httpClient = app.ApplicationServices.GetService<IHttpClientFactory>().CreateClient();
MyStaticObject.Configure(myOptions, httpClient);
var myOptions=app.ApplicationServices.GetService();
HttpClient HttpClient=app.ApplicationServices.GetService().CreateClient();
配置(myOptions,httpClient);

编辑:添加了一些示例代码。

这里有几点要看,首先是
MyStaticObject
是否真的需要是静态的?如果是这样,我建议将其注册为单例,这样您仍然可以利用依赖项注入。完成此操作后,您可以注册
IHttpClientFactory
,并从代码中使用它。您的
ConfigureServices
方法可能最终看起来像这样

public void ConfigureServices(IServiceCollection services)
{
  //The base extension method registers IHttpClientFactory
  services.AddHttpClient();
  services.AddSingleton<IMySingletonObject, MySingletonObject>();
}
原因是
IHttpClientFactory
为我们处理生命周期和池问题。根据:

管理底层HttpClientMessageHandler实例的池和生存期。自动管理避免了手动管理HttpClient生命周期时出现的常见DNS(域名系统)问题

当您进行
CreateClient
调用时会发生这种情况,因此您希望使用客户端在代码内部执行此操作,而不是在应用程序启动时执行此操作


作为补充说明,如果您根本不需要将该类作为单例,那么可以使用扩展名
services.AddHttpClient()
并将
HttpClient
直接插入到该类中。DI容器将为您处理从工厂后台获取客户机的问题。

这里有几件事要看,第一件事是
MyStaticObject
是否真的需要是静态的?如果是这样,我建议将其注册为单例,这样您仍然可以利用依赖项注入。完成此操作后,您可以注册
IHttpClientFactory
,并从代码中使用它。您的
ConfigureServices
方法可能最终看起来像这样

public void ConfigureServices(IServiceCollection services)
{
  //The base extension method registers IHttpClientFactory
  services.AddHttpClient();
  services.AddSingleton<IMySingletonObject, MySingletonObject>();
}
     public static IServiceCollection AddApiClient(this IServiceCollection services,
        Action<RgCommunicationClientOptions> action)
    {
        services.AddHttpClient<ISomeApiClient, SomeApiClient>()
            .AddPolicyHandler(GetRetryPolicy())
            .SetHandlerLifetime(TimeSpan.FromMinutes(4));
        services.AddOptions();
        services.Configure(action);

        return services;
    }
    
    static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
    {
        return HttpPolicyExtensions
            .HandleTransientHttpError()
            //.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
            .WaitAndRetryAsync(2, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
    }

 services.AddApiClient(options => options.BaseAddress = configuration.GetSection("ExternalServices:SomeApi")["Url"]);
       
原因是
IHttpClientFactory
为我们处理生命周期和池问题。根据:

管理底层HttpClientMessageHandler实例的池和生存期。自动管理避免了手动管理HttpClient生命周期时出现的常见DNS(域名系统)问题

当您进行
CreateClient
调用时会发生这种情况,因此您希望使用客户端在代码内部执行此操作,而不是在应用程序启动时执行此操作

作为补充说明,如果您根本不需要将该类作为单例,那么可以使用扩展名
services.AddHttpClient()
并将
HttpClient
直接插入到该类中。DI容器将为您处理从工厂后台获取客户端的操作。

公共静态IServiceCollection AddApicClient(此IServiceCollection服务,
     public static IServiceCollection AddApiClient(this IServiceCollection services,
        Action<RgCommunicationClientOptions> action)
    {
        services.AddHttpClient<ISomeApiClient, SomeApiClient>()
            .AddPolicyHandler(GetRetryPolicy())
            .SetHandlerLifetime(TimeSpan.FromMinutes(4));
        services.AddOptions();
        services.Configure(action);

        return services;
    }
    
    static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
    {
        return HttpPolicyExtensions
            .HandleTransientHttpError()
            //.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
            .WaitAndRetryAsync(2, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
    }

 services.AddApiClient(options => options.BaseAddress = configuration.GetSection("ExternalServices:SomeApi")["Url"]);
       
行动(行动) { services.AddHttpClient() .AddPolicyHandler(GetRetryPolicy()) .SetHandlerLifetime(TimeSpan.FromMinutes(4)); services.AddOptions(); 服务。配置(操作); 返回服务; } 静态IAsyncPolicy GetRetryPolicy() { 返回HttpPolicyExtensions .HandleTransientHttpError() //.OrResult(msg=>msg.StatusCode==System.Net.HttpStatusCode.NotFound) .WaitAndRetryAsync(2,retrytry=>TimeSpan.FromSeconds(Math.Pow(2,retrytry)); } services.AddApiClient(options=>options.BaseAddress=configuration.GetSection(“ExternalServices:SomeApi”)[“Url”];
您可以像上面那样通过依赖项注入在类中注入HttpClient。我已经使用Poly扩展添加了RetryPolicy。还可以使用sethaandlerlife设置处理程序的LifetTime。通过这种方式,您可以为每个客户机单独配置客户机。在日志中,您可以看到httpHandler在相应调用的4分钟后过期。我使用扩展方法传递方法中的选项,通过应用程序设置获取值。 希望这有帮助。 大宗报价

公共静态IServiceCollection AddApicClient(此IServiceCollection服务,
行动(行动)
{
services.AddHttpClient()
.AddPolicyHandler(GetRetryPolicy())
.SetHandlerLifetime(TimeSpan.FromMinutes(4));
services.AddOptions();
服务。配置(操作);
返回服务;
}
静态IAsyncPolicy GetRetryPolicy()
{
返回HttpPolicyExtensions
.HandleTransientHttpError()
//.OrResult(msg=>msg.StatusCode==System.Net.HttpStatusCode.NotFound)
.WaitAndRetryAsync(2,retrytry=>TimeSpan.FromSeconds(Math.Pow(2,retrytry));
}
services.AddApiClient(options=>options.BaseAddress=configuration.GetSection(“ExternalServices:SomeApi”)[“Url”];
您可以像上面那样通过依赖项注入在类中注入HttpClient。我已经使用Poly扩展添加了RetryPolicy。还可以使用sethaandlerlife设置处理程序的LifetTime。通过这种方式,您可以为每个客户机单独配置客户机。在日志中,您可以看到httpHandler在相应调用的4分钟后过期。我使用扩展方法传递方法中的选项,通过应用程序设置获取值。 希望这有帮助。 大宗报价


您在哪里实例化您的HttpClient?如果您使用的是HttpClientFactory,它将处理