.NET Core 3.1 Web API请求超时设置不生效,原因是什么?
问题原因与解决方案
你设置的KeepAliveTimeout完全不是用来控制请求处理超时的——它的作用是维持客户端与服务器的空闲连接时长:当连接建立后,如果一段时间内没有新的请求发送,服务器会在超时后关闭这个连接,和单个请求的处理耗时没有任何关系。这就是为什么你的测试请求等了100秒还是返回200的原因。
要实现「请求处理超时后返回504」的需求,你需要用以下方式:
1. 自定义超时中间件
在ASP.NET Core 3.1中没有内置的请求超时中间件,需要自己实现一个,核心思路是给每个请求绑定一个取消令牌,超时后触发取消并返回504:
中间件代码
public class RequestTimeoutMiddleware { private readonly RequestDelegate _next; private readonly int _timeoutMs; public RequestTimeoutMiddleware(RequestDelegate next, int timeoutMs) { _next = next; _timeoutMs = timeoutMs; } public async Task InvokeAsync(HttpContext context) { // 创建超时取消令牌 using var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromMilliseconds(_timeoutMs)); // 替换请求的取消令牌,让后续处理能响应超时 context.RequestAborted = timeoutTokenSource.Token; try { await _next(context); } catch (OperationCanceledException) when (timeoutTokenSource.Token.IsCancellationRequested) { // 超时触发时返回504 context.Response.StatusCode = StatusCodes.Status504GatewayTimeout; await context.Response.WriteAsync("请求处理超时,请稍后重试"); } } }
注册中间件
在Startup.cs的Configure方法中,把这个中间件放在最前面(确保所有后续请求处理都受它控制):
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // 注册超时中间件,设置10秒超时 app.UseMiddleware<RequestTimeoutMiddleware>(10000); // 其他中间件(路由、控制器等)放在后面 app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
2. 让业务代码响应取消令牌
你的测试代码用了Thread.Sleep(100000),这是同步阻塞操作,不会响应取消令牌。要让超时生效,需要改成支持取消的异步操作:
// 替换Thread.Sleep(100000)为: await Task.Delay(100000, HttpContext.RequestAborted);
这样当超时触发时,Task.Delay会抛出OperationCanceledException,被中间件捕获后返回504。
内容的提问来源于stack exchange,提问作者A. Hasemeyer
相关产品推荐
相关产品推荐

