rud*_*ter 3 dependency-injection httpclient asp.net-core httpclientfactory
我在工厂中注册我的 HttpClient:
services.AddHttpClient<ICatalogService, CatalogService>()
.SetHandlerLifetime(TimeSpan.FromMinutes(2));
Run Code Online (Sandbox Code Playgroud)
此 ICatalogService 通过构造函数注入到单例服务中。
2 分钟后我会在内部收到一个新的 HttpMessageHandler 还是仅在 2 分钟后将 ICatalogService 注入到非单例服务中?
基本上,当包装 HttpHandler 用作单例时,内部 HttpMessageHandler 也会过期吗?
\n\n当包装 HttpHandler 用作单例时,内部 HttpMessageHandler 也会过期吗?
\n
警告:HttpClient通过单例保持实例活动并不安全。
配置的HttpMessageHandler实例将在两分钟后过期。在到期日期之后HttpClient创建的任何内容都将获得包含新到期日期的新内容。但这对保持活动状态的实例没有帮助。HttpMessageHandlerHttpClient
重要提示: 只要它存在,HttpClient就会继续使用它,因此,\n不尊重 DNS 更改。只有新实例才会看到 DNS 更新。HttpMessageHandlerHttpMessageHandler
这意味着只要您保持HttpClient活动状态,HttpClient就会错过 DNS 更改,这就是HttpClient实例只能存活很短一段时间的原因。HttpClient只要您重用底层实例HttpMessageHandler(这就是基础设施为您所做的),创建和清理实例的成本就非常低。
不幸的是,在您的情况下,您HttpClient被注入到CatalogService,而 被注入到Singleton消费者中。保持Singleton活动CatalogService状态,因此HttpClient在应用程序\xe2\x80\x94的持续时间内间接保持活动状态您HttpClient现在是Captive Dependency。
您遇到的是新的 .NET CoreIHttpClientFactory基础架构中的一个不幸的设计缺陷。我认为这是一个缺陷,因为 IMO 基础设施应该阻止您将HttpClient实例捕获,例如通过将客户端(您的CatalogService)注册为Scoped. 我早在 2019 年 1 月就报告了这个问题。微软已经承认了这个问题,但截至撰写本文时,还没有可用的解决方案。
由于还没有解决方案,因此您必须非常小心,不要导致HttpClient作为 Captive Dependency 保持活动状态。这意味着您不能将其注入Singleton消费者(甚至是间接消费者)。
防止这种情况的一个好方法是将客户端(您的CatalogService)注册为Scoped。这允许框架的配置系统验证它是否被注入到Singleton. 但由于没有对此的直接支持,您必须手动进行注册,例如使用以下扩展方法:
public static IHttpClientBuilder AddTypedClientScoped<TClient>(\n this IHttpClientBuilder builder)\n where TClient : class\n{\n ...\n builder.Services.AddScoped<TClient>(s =>\n {\n var httpClientFactory = s.GetRequiredService<IHttpClientFactory>();\n var httpClient = httpClientFactory.CreateClient(builder.Name);\n var factory = s.GetRequiredService<ITypedHttpClientFactory<TClient>>();\n return factory.CreateClient(httpClient);\n });\n\n return builder;\n}\nRun Code Online (Sandbox Code Playgroud)\n在调试时启动 ASP.NET Core 网站时,框架将为您验证范围,这会在客户端注入单例时导致异常。
\n但请注意,使用此扩展方法不会检测所有捕获HttpClient实例。这是因为 ASP.NET Core 中的某些位置组件被注册为Transient在应用程序持续时间内仍保持活动状态。托管服务就是这样的案例之一。扩展AddHostedService方法就是这样的例子。Transient托管服务在保持活动状态时注册为Singleton。在我看来,这是另一个设计缺陷。但这意味着您在直接或间接将HttpClient实例注入托管服务时应该小心。
| 归档时间: |
|
| 查看次数: |
1711 次 |
| 最近记录: |