【问题标题】:ClientConnectionFailure at forward-request转发请求时的 ClientConnectionFailure
【发布时间】:2021-02-18 16:01:25
【问题描述】:

我有一个 Angular Web 应用程序,它由 C# Web Api 支持,它有助于与 Azure Function App 对话。

一个粗略的示例流程如下:

  • Angular Web App(使用所选参数按下载)-> 向 API 管理服务发送 GET 请求
  • API 管理服务调用 C# Web Api
  • C# Web Api 然后响应 APIM,APIM 反过来调用 Azure Function App 以进一步处理 来自外部来源的数据
  • 准备好 csv 后,将在打开 Web 应用的浏览器中下载数据负载

对于较大的有效负载,下载请求失败,Application Insights 中出现以下错误:

"ClientConnectionFailure at forward-request"

除非有效负载足够小,否则此错误每次恰好发生在 2 分钟。

这让我相信,在这种情况下,我理解为客户端的 Function App 正在超时并取消请求。

但是使用 Postman 通过 Azure Function App 的本地实例测试具有完全相同参数的 GET,有效负载被成功检索。

所以问题不在于 Azure Function App,因为它在 Postman 中没有像使用 WebApp 时那样超时。

这让我想到了三种不同的可能性:

  1. C# WebApi 超时并在 APIM 可以完全响应之前取消请求
  2. WebApp 本身正在超时。
  3. 互联网浏览器 (Chrome) 正在超时。 (Chrome 有 5 分钟的硬性不可更改超时,所以不太可能)

#1。为了解决第一个选项,我升级了在相关下载操作中创建的 HttpClient 的超时:

public aync Task<HttpResponseMessage> DownloadIt(blah)
{
    HttpClient client = getHttpClient();
    client.Timeout = TimeSpan.FromMilliseconds(Convert.ToDouble(600000)); // 10 minutes
    var request = new HttpRequestMessage(HttpMethod.Get, buildQueryString(blah, client.BaseAddress));
    return await client.SendAsync(request);
}

private HttpClient getHttpClient()
{
    return _httpClientFactory.CreateClient("blah");
}

这没有影响,因为观察到了同样的错误。

#2。 protractor.conf.js 中有几个 Timeout 属性,例如 allScriptsTimeoutdefaultTimeoutInterval

增加这些没有效果。

** 最后一种可能性是 APIM 本身超时,但是查看相关 API 的 APIM 策略,没有 forward-request 属性,有超时,这意味着根据微软默认情况下,有APIM 没有超时。 https://docs.microsoft.com/en-us/azure/api-management/api-management-advanced-policies

我尝试了几种不同的策略,但都无济于事。

【问题讨论】:

    标签: c# angularjs azure http azure-api-management


    【解决方案1】:

    在本地(Azure外部)、web app(前端)、web api、function app(后端)测试解决方案的各个组件后,很明显问题是Azure本身造成的,即默认4分钟Azure 负载均衡器的空闲超时。

    我通过对失败的请求计时并且总是得到 4 分钟来仔细检查。

    后端代码发送请求的方式是一起的,对于更大的数据集,这会导致它达到负载均衡器的超时。

    看起来负载平衡器超时是可配置的,但这看起来我无法更改。

    所以解决方案:在后端编写更高效/更好的代码。

    【讨论】:

      【解决方案2】:

      您可以在整个函数应用或单个端点上显式设置转发请求,例如:

      <backend>
           <forward-request timeout="1800" />
      </backend>
      

      时间以秒为单位(此处为 1800*60 = 60 分钟)

      要在 APIM 中执行此操作,

      1. 转到您的 APIM
      2. API
      3. 选择您的函数应用
      4. 点击Inbound Processing下的代码图标&lt;/&gt;

      或者,如果您只想对单个操作/端点执行此操作,请在执行第 4 步之前单击单个操作/端点。

      【讨论】:

      • 这也被尝试过,但这不是解决方案。这实际上是由于 Azure 在其主干网络上的 4 分钟锁定请求超时造成的。
      【解决方案3】:

      确实存在超时,因为 ClientConnectionFailure 表明客户端关闭了与 API 管理 (APIM) 的连接,而 APIM 尚未向它(客户端)返回响应,在这种情况下,它正在将请求转发到后端(forward-request)

      要调试此类问题,最好的方法是收集 APIM inspector trace 以检查 APIM 管道内的请求处理,注意请求每个部分所花费的时间 - Inbound、Backend、Outbound。花费最多时间的部分可能是罪魁祸首(或者它的依赖项)。希望这可以帮助您找出问题所在。

      【讨论】:

      • 所以在跟踪遥测中,webapi 向 APIM 发送 HTTP GET 请求。 APIM 收到请求,然后 bam,抛出异常,操作被取消。那么在这种情况下,Client就是webapi?
      • 如果 Web API 将请求发送到 APIM,那么是的,它是客户端(到 APIM)。但是从您在问题中描述的流程来看,客户端似乎是 Angular Web App - Angular Web App -> APIM -> C# Web API。
      • 是否有可能因为更大的有效负载,HTTP ExecutionTimeout 被命中(默认 110 秒),这就是取消发生的地方?
      • payload的大小对时间有影响。不确定这个默认设置在哪里,但如果是在客户端上,那么是的,因为客户端是关闭连接的那个。
      • 我能够确定的一件事是在本地测试时不会发生这种行为。 webapi 不会遇到任何超时问题。将代码中的任务更改为同步运行允许在某些情况下在 Azure 中取消 2.0 分钟超时。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-26
      • 2019-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多