【问题标题】:HttpClient very slow with Windows AuthenticationHttpClient 使用 Windows 身份验证非常慢
【发布时间】:2018-11-22 17:01:27
【问题描述】:

我有一个内部公司 API,我通过 HttpClient 从 dotnet 核心网站调用它。 API 托管在启用了 Windows 身份验证的 IIS 网站中。 API 中的身份验证通过此方案执行。但是,Web 请求非常慢,因为 HttpClient 执行的质询-响应过程在从 API 服务器接收到的 401 响应和 HttpClient 发送具有必要授权标头的后续(成功)请求之间包含大约 0.4 秒的巨大间隙。

HttpClient 通常是通过 HttpClientFactory 注入的,但为了清楚起见,这里是等效的内联代码(问题存在,但是 HttpClient 是实例化的):

using (HttpClient httpClient = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }, true))
{
     httpClient.BaseAddress = new System.Uri( "https://localhost:60491/myapi/api/Internal/");
     var response = await httpClient.PutAsync(uri, content);

     await ValidateResponseAsync(response);
}

然后,在服务器上,日志会显示对初始请求的 401 响应与下一个带有 Authorization 标头的请求之间存在 0.4 秒的间隔:

15:56:09.80114 [INF] HTTP "PUT" "/api/Internal/Documents/989898989" 在 1.4533 毫秒内响应 401。 用户为空

15:56:10.17185 [INF] 请求 启动 HTTP/1.1 PUT http://localhost:60491/myapi/api/Internal/Documents/989898989 应用程序/json 750

这不是与网络相关的问题,因为该网站是本地网站。我通过网络浏览器执行了完全相同的请求,浏览器接收到的 401 与下一个请求之间的差异是 0.001 秒。对于来自浏览器的整个 PUT 请求(包括 401 和 204 响应)需要 0.05 秒,来自 HttpClient 需要 0.4 秒。性能差异完全是由于发送带有 Authorization 标头的请求的差距。

我不能在 HttpClientHandler 上使用 PreAuthenticate 标志,因为这是特定于 Uri 的,而且我的请求包含的 ID 会在每个请求之间有所不同。

有没有人知道为什么会发生这种情况,更好的是,如何解决它?

【问题讨论】:

  • 当您通过浏览器访问时,您的登录方式是否与使用 HttpClient 的程序相同(例如,您使用的是服务帐户而不是您的个人登录帐户)?有许多设置可能不同,例如代理设置。此外,请考虑获取证书,因为localhost 的 TLS 验证可能会失败并退回。要么使用http:——为本地主机连接添加https实际上并不能提高你的安全基础。
  • 两种情况下的登录名相同。我已将 HttpClientHandler 上的 UseProxy 设置为 false(没有为浏览器设置代理)。 localhost 网站使用受信任的 ISS Express 开发证书。无论如何,我们的测试服务器上也会发生同样的行为,因此它并不特定于我的本地环境,
  • 您可能需要设置 WIreshark 并查看流量。将它们并排放置并寻找差异。浏览器可能正在执行某种缓存或有其他一些技巧来提高吞吐量。

标签: c# iis asp.net-core windows-authentication dotnet-httpclient


【解决方案1】:

默认情况下HttpClientHandler 默认启用属性UseProxy。我遇到过类似的情况,它试图使用系统默认设置查找代理,设置为“自动配置代理”,增加了很大的延迟。

当您初始化HttpClientHandler 时,将UseProxy 设置为false,这可能会使问题消失。

【讨论】:

  • 嗨,Scott,谢谢,我认为这已经解决了它,但后来看到已经设置了一个标志来授权开发环境中的任何请求,因此在初始请求时没有发回 401。当我删除它并返回 401 时,在接收 401 和使用 Authorization 标头发出成功请求之间再次发生 0.4 秒的延迟。
【解决方案2】:

你不能设置一个更快的超时时间吗? https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient.timeout?redirectedfrom=MSDN&view=netframework-4.7.2

我假设这会以某种方式在请求中进行编码,并在客户端内部使用。我读过 .net Core httpClient 在 2.0 中非常慢,在 2.1 中要快得多,您还可以检查代理设置,因为这可能是 .Net Core httpClient 中的问题。

【讨论】:

  • 它没有超时,所以我看不出更改 Timeout 属性有什么帮助?请求成功,就是慢。我使用的是核心 2.1,所以也不是这样。
  • 你能看到 Telerik Fiddler 或 Wireshark 在网络上发生了什么吗?
【解决方案3】:

您不应该为每个请求创建一个新的 HttpClient,这是您的 using 语句所做的。

https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client

HttpClient 旨在被实例化一次并在应用程序的整个生命周期中重复使用。

【讨论】:

  • 正如我在问题中提到的,这不是网站中运行的实际代码。 HttpClient 实际上是通过 DI 设置的 IHttpClientFactory 注入的,因此不会每次都实例化。为了清楚起见,我只是使用该代码 sn-p 来显示针对 HttpClientHandler 设置的属性。无论是每次根据代码块还是通过工厂实例化都会导致相同的性能问题。
  • 我的直觉是尝试使用 Post 而不是 Put,我在使用 PUT 时遇到了类似的问题。希望这会有所帮助
  • 在回答之前阅读帖子会更好
猜你喜欢
  • 1970-01-01
  • 2018-06-27
  • 1970-01-01
  • 1970-01-01
  • 2014-10-25
  • 2019-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多