IIS托管ASP.NET Core 6 Web API返回结果时客户端挂起排查
问题环境
在Windows 10系统的IIS 10上部署了基于.NET 6开发的ASP.NET Core Web API应用,服务核心逻辑为调用外部API后将结果返回给调用方,保留关键逻辑的简化代码如下:
[ApiController] [Produces("application/json")] public class SomeController { private async Task<ApiOutput> RunApiForClientAsync(ApiInput input) { try { //create a httpclient with a lot of configuration var response = await client.SendAsync(request); var content = await response.Content.ReadAsStringAsync(); return new ApiOutput { Data = content, Error = null, StatusCode = 200, Input = input, }; } catch(Exception ex) { return new ApiOutput { Data = null, Error = new ApiError("Error Getting the Result from the Server", ex.Message), StatusCode = 400, Input = input, }; } } private async Task<List<ApiOutput>> RunApiCallsAsync(string requestId, IEnumerable<ApiInput> items) { var result = new List<ApiOutput>(); var tasks = new List<Task<ApiOutput>>(); foreach(var item in items) { tasks.Add(RunApiForAsync(item)); } var taskResults = await Task.WhenAll(tasks); result.AddRange(taskResults); return result; } [HttpPost] [Route("rest/multiple")] public async Task<IActionResult> PostMultiple(ApiInput[] models, string? requestId) { _logger.LogInformation(ApiLoggingEvents.PostMultiple, "Request received with ID {requestId}", requestId); var result = await RunApiCallsAsync(requestId, models); try { _logger.LogDebug(ApiLoggingEvents.PostMultiple, "Request ID {requestId} Generating JSONs.", requestId); var resultJson = GetJson(result); await SaveResultAsync(resultJson, requestId); _logger.LogDebug(ApiLoggingEvents.PostMultiple, "Request ID {requestId} Everything is finished. Returning....", requestId); return Content(resultJson, "application/json"); } catch (Exception ex) { _logger.LogDebug(ApiLoggingEvents.PostMultiple, "Exception while returning {requestId}, message {msg}", requestId, ex.Message); throw new Exception("Try again"); } } }
故障现象
服务偶发出现调用方发起请求后始终无法收到响应的问题,但查看服务端日志可见对应请求已执行到打印Everything is finished. Returning的步骤,证明业务逻辑全部执行成功;同时await SaveResultAsync(resultJson, requestId);执行正常,结果JSON已保存到服务器本地磁盘。出现该问题的均为长耗时请求,通常响应时长约10分钟。
曾尝试通过如下代码配置Kestrel参数,但该配置对IIS In-Process托管模式不生效:
builder.WebHost.UseKestrel(o => { o.Limits.MaxConcurrentConnections = 100; o.Limits.KeepAliveTimeout = TimeSpan.FromMilliseconds(timeout); o.Limits.MaxRequestBodySize = int.MaxValue; o.Limits.MaxResponseBufferSize = int.MaxValue; });
说明:每个请求携带唯一GUID类型的
requestId参数,用于日志中追踪请求链路、校验请求执行状态、确认结果文件是否生成。
排查进展
- 初步排查发现运行时长超过5分钟的请求均会出现该异常,暂未定位到和5分钟阈值相关的配置项;
- 为复现问题新增了指定延迟时长后返回简单消息的测试接口,代码如下:
[HttpPost] [Route("rest/testpost")] public IActionResult TestPost(int delay) { _logger.LogInformation(1, "Delay for {delay} started.", delay); Thread.Sleep(delay * 1000); _logger.LogInformation(1, "Delay for {delay} ended.", delay); return Ok($"Delay for {delay} worked."); }
- 已在web.config中配置
requestTimeout="00:20:00"延长超时时间,但测试发现延迟设置为310秒的请求,依然存在偶发无法返回结果、Postman持续挂起的情况:
现咨询该问题的解决方案,确认是否需要调整应用侧或IIS侧的相关配置。
内容的提问来源于stack exchange,提问作者Alireza Noori
相关产品推荐
相关产品推荐

