我有一个Angular Web应用程序,它由C#Web Api支持,它有助于与Azure Function应用程序对话。
一个粗略的流程示例如下:
- Angular Web应用程序(按下载并选择参数(->向API管理服务发送GET请求
- API管理服务调用C#Web API
- 然后,C#Web Api响应APIM,APIM反过来调用Azure函数应用程序进行进一步处理来自外部源的数据
- csv准备就绪后,数据有效载荷将下载到打开Web应用程序的浏览器中
对于较大的有效载荷,下载请求失败,Application Insights中出现以下错误:
"ClientConnectionFailure at forward-request"
除非有效载荷足够小,否则每次错误发生的时间正好为2分钟。
这让我相信,在这种情况下,我理解为客户的功能应用程序正在超时并取消请求。
但是,使用Postman通过Azure Function App的本地实例测试具有完全相同参数的GET,可以成功检索到有效载荷。
所以问题不在于Azure Function应用程序,因为它在Postman中没有像使用WebApp时那样超时。
这让我想到了三种不同的可能性:
- C#WebApi超时并在APIM完全响应之前取消请求
- WebApp本身已经超时
- 互联网浏览器(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.在dractor.conf.js中有几个Timeout属性,如allScriptsTimeout
和defaultTimeoutInterval
。
增加这些没有任何效果。
**最后一种可能性是APIM本身超时,但查看相关API的APIM策略,不存在带有超时的转发请求属性,这意味着根据微软的说法,默认情况下,APIM没有超时。https://learn.microsoft.com/en-us/azure/api-management/api-management-advanced-policies
我尝试了几种不同的策略,但都无济于事。
确实存在超时,因为ClientConnectionFailure指示客户端关闭与API管理(APIM(的连接,而APIM尚未返回对其(客户端(的响应,在这种情况下,它正在将请求转发到后端(转发请求(
要调试这类问题,最好的方法是收集APIM检查器跟踪,以检查APIM管道内的请求处理,并注意在请求的每个部分(入站、后端、出站(上花费的时间。花费时间最多的部分可能是罪魁祸首(或者它的依赖关系(。希望这能帮助你找到问题所在。
您可以在整个函数应用程序或单个端点上显式设置转发请求,例如:
<backend>
<forward-request timeout="1800" />
</backend>
其中时间以秒为单位(此处为1800*60=60分钟(
要在APIM、中做到这一点
- 转到您的APIM
- API
- 选择您的功能应用程序
- 单击
Inbound Processing
下的代码图标</>
或者,如果只想对单个操作/端点执行此操作,请在执行步骤4.之前单击单个操作/终结点。
在本地(Azure外部(测试了解决方案的每个组件、web应用程序(前端(、web api、功能应用程序(后端(后,很明显问题是由Azure本身引起的,即Azure负载均衡器的默认空闲超时为4分钟。
我通过计时失败的请求进行了仔细检查,总是有4分钟的时间。
后端中的代码发送请求的方式是一起的,对于较大的数据集,这导致它达到负载均衡器的超时。
负载均衡器超时看起来是可配置的,但这看起来不像是我可以更改的。
因此解决方案:在后端编写更高效/更好的代码。