转发请求时出现ClientConnectionFailure

问题描述

我有一个Angular Web应用程序,该应用程序由C#Web Api支持,可以方便地与Azure Function应用程序进行通话。

一个大致的示例流程如下:

  • Angular Web App(按下载并选择参数)->将GET请求发送到API管理服务
  • 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应用程序,因为在Postman中使用WebApp时没有超时。

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

  1. C#WebApi在APIM不能完全响应之前正在超时并取消请求
  2. WebApp本身正在超时。
  3. Internet浏览器(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中有几个超时属性,例如allScriptsTimeoutdefaultTimeoutInterval

增加这些没有效果

**最后一种可能是APIM本身正在超时,但是在调查相关API的APIM策略时,不存在带有超时的转发请求属性,这意味着根据Microsoft的认设置,存在APIM没有超时。 https://docs.microsoft.com/en-us/azure/api-management/api-management-advanced-policies

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

解决方法

确实存在超时,因为ClientConnectionFailure指示客户端在APIM尚未向其返回响应(客户端)时关闭了与API Management(APIM)的连接,在这种情况下,客户端正在将请求转发至后端(forward-request

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

,

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

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

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

要在 APIM 中执行此操作,

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

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

,

在本地(Azure 外部)、Web 应用(前端)、Web api、函数应用(后端)测试解决方案的各个组件后,很明显问题是由 Azure 本身引起的,即默认 4 分钟Azure 负载均衡器的空闲超时。

我通过计时失败的请求进行了双重检查,并且总是有 4 分钟。

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

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

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