【问题标题】:Is HttpClient safe to use concurrently?同时使用 HttpClient 是否安全?
【发布时间】:2023-03-05 21:37:01
【问题描述】:

在我能找到HttpClient 用法的所有示例中,它用于一次性通话。但是,如果我有一个持久的客户端情况,可以同时发出多个请求怎么办?基本上,针对 HttpClient 的同一个实例一次在 2 个线程上调用 client.PostAsync 是否安全。

我并不是真的在这里寻找实验结果。作为一个工作示例可能只是一个侥幸(并且是一个持久的),而一个失败的示例可能是一个错误配置问题。理想情况下,我正在为 HttpClient 中的并发处理问题寻找一些权威的答案。

【问题讨论】:

标签: .net c#-4.0 concurrency dotnet-httpclient


【解决方案1】:

According to Microsoft Docs,从 .NET 4.5 开始以下实例方法是线程安全的(感谢@ischell):

CancelPendingRequests
DeleteAsync
GetAsync
GetByteArrayAsync
GetStreamAsync
GetStringAsync
PostAsync
PutAsync
SendAsync
PatchAsync

【讨论】:

  • 是的,我不确定那个,因为它似乎是 MSDN 上所有内容的标准警告(我记得读过一些 MSDN 博客关于有时该警告是错误的,因为它是盲目地应用于一切)。
  • 这是错误的;在您链接的 MSDN 页面的备注部分中,它说 GetAsync、PostAsync 等都是线程安全的。
  • @ischell:我可以向你保证,在讨论这个问题时,有问题的段落不存在
  • 所以微软将 HttpClient 设计为可重用,但该类具有标头的实例数据:client.DefaultRequestHeaders.Accept.Add(...);
  • 迟了,但我想对@cwills 发表评论。 DefaultRequestHeaders 就是这样,默认值。如果您想要基于每个请求的不同标头,您可以创建新的 StringContent(),在其上设置其他标头,然后使用采用 URI 和 HttpContent 的重载。
【解决方案2】:

这是来自 Henrik F. Nielsen 的另一个 article 关于 HttpClient,他说:

"默认的 HttpClient 是您可以开始发送请求的最简单方式。单个 HttpClient 可用于同时发送任意数量的 HTTP 请求,因此在许多情况下,您可以只创建一个 HttpClient,然后将其用于所有请求。"

【讨论】:

  • 如果用户名和密码可以在线程之间更改怎么办?这就是我似乎找不到任何人在谈论的事情
  • @NicholasDiPiazza:它多久更改一次?如果有一组已知的用户/密码对,那么您可以创建一个 HttpClient 实例池。
  • 是的,这就是我最终做的事情
  • 请注意,对所有请求重复使用相同的 HttpClient 可能会导致过时的 DNS 问题:github.com/dotnet/corefx/issues/11224
  • @OhadSchneider 如果认为该问题仅限于 .net 核心。您可以通过将自定义 HttpClientHandler 注入 HttpClient 构造函数然后设置“ConnectionLeaseTimeout”来解决 .net 4 的问题。但是,如果 100 秒内没有向端点发送请求,则连接将自行刷新。 protected override Task SendAsync(HttpRequestMessage request,CancellationToken cancelToken) { var sp = ServicePointManager.FindServicePoint(request.RequestUri); sp.ConnectionLeaseTimeout = 100 * 1000; }
【解决方案3】:

找到了 Henrik F. Nielsen(HttpClient 的主要架构师之一)的 MSDN forum post

快速总结:

  • 如果您有相关的请求(或不会相互影响),那么使用相同的 HttpClient 很有意义。

  • 一般来说,我建议尽可能重用 HttpClient 实例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-22
    相关资源
    最近更新 更多