.NET Core使用Task.WhenAll并行调用Web Service部署IIS返回202问题排查
问题排查与解决方案
首先可以明确:该问题不是await Task.WhenAll的正常行为,Task.WhenAll仅负责等待所有并行任务执行完成,不会修改任何请求的响应结果,你的基础并行调用逻辑没有语法错误,问题来源于代码可优化点和部署环境配置,可按以下方向排查修改:
1 代码优化(HttpClient使用规范问题)
你当前的代码中每次调用Test方法都调用_clientFactory.CreateClient()创建新的客户端实例,虽然IHttpClientFactory会自动管理连接池生命周期,但高并发下频繁创建实例会增加不必要的开销,同时默认的HttpClient配置没有针对高并发出站请求做优化,可按以下方式修改:
1.1 注册命名HttpClient(Startup.cs)
services.AddHttpClient("TargetApiClient", c => { // 提前配置目标API的公共参数,避免每次请求重复设置 c.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Bearer 你的实际token"); }) .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { // 手动调大同一目标域名的最大并发连接数,避免连接池限制 MaxConnectionsPerServer = 100, AutomaticDecompression = System.Net.DecompressionMethods.GZip | System.Net.DecompressionMethods.Deflate });
1.2 控制器内复用HttpClient实例
public class TestsController : ControllerBase { private readonly HttpClient _targetClient; // 其他注入项保持不变 public TestsController(IHttpClientFactory clientFactory, /*其他参数*/) { // 仅在构造函数中创建一次HttpClient实例,全程复用 _targetClient = clientFactory.CreateClient("TargetApiClient"); } public async Task<string> Test(int counter) { var requestData = new HttpRequestMessage(HttpMethod.Get, "你的目标API完整地址"); var results = await _targetClient.SendAsync(requestData); var json = await results.Content.ReadAsStringAsync(); return $"Task {counter} {results.StatusCode};"; } // 其他方法保持不变 }
2 部署环境排查
你提到本地运行正常、JMeter直接调用目标API正常,基本可以确定问题出在部署到IIS后的运行环境,可按以下顺序排查:
- 检查IIS相关模块配置:确认IIS是否安装了ARR(应用程序请求路由)、反向代理等模块,这类模块默认会限制出站请求的并发数,高并发下会触发限流返回非200状态码,可调整对应模块的并发连接数限制,或者禁用不必要的出站代理规则。
- 调整Windows Server TCP参数:高并发出站请求会占用大量临时端口,Windows Server默认的临时端口范围和连接数限制可能不足,可修改注册表
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters下的MaxUserPort(建议设为65534)、TcpTimedWaitDelay(建议设为30)参数,修改后重启服务器生效。 - 升级.NET Core版本:.NET Core 2.2已于2019年停止官方支持,存在大量已知的HttpClient高并发相关bug,建议至少升级到.NET Core 3.1 LTS,优先选择.NET 6/8 LTS版本,可直接修复大量底层运行时问题。
3 辅助排查手段
如果以上修改后问题仍存在,可通过以下方式定位根因:
- 在
Test方法中记录所有响应的头信息和完整响应体,确认202状态码的返回来源,通常反向代理/限流组件返回的202会带特殊标识头。 - 在部署服务器上使用Wireshark/Fiddler抓取出站HTTP请求,对比请求内容和JMeter发送的请求是否完全一致,确认是否有中间节点篡改了请求或响应。
内容的提问来源于stack exchange,提问作者Rabin
相关产品推荐
相关产品推荐

