.NET 8 中的请求超时中间件

作者:微信公众号:【架构师老卢】
6-5 17:47
28

概述:在本文中,我们将学习如何使用 Microsoft.AspNetCore.Http.Timeouts 命名空间在 .NET 8 中请求超时中间件工作。此命名空间提供了应用每个请求的超时的灵活性。当达到超时限制时,HttpContext.RequestAborted 中 CancellationToken 的 IsCancellationRequested 属性设置为 true。但是,请求不会自动中止,因此应用程序仍会生成成功或失败响应。如果应用程序未处理异常并生成响应,则默认行为是返回状态代码 504。作者创建的图像如何配置 RequestTimeout 中间件?让我们看看如何为标准 .NET

在本文中,我们将学习如何使用 Microsoft.AspNetCore.Http.Timeouts 命名空间在 .NET 8 中请求超时中间件工作。此命名空间提供了应用每个请求的超时的灵活性。当达到超时限制时,HttpContext.RequestAborted 中 CancellationToken 的 IsCancellationRequested 属性设置为 true。但是,请求不会自动中止,因此应用程序仍会生成成功或失败响应。如果应用程序未处理异常并生成响应,则默认行为是返回状态代码 504。

作者创建的图像

如何配置 RequestTimeout 中间件?

让我们看看如何为标准 .NET Web API 和最小 API 配置超时中间件。现在让我们看看如何增加Program.cs

using Microsoft.AspNetCore.Http.Timeouts;  
using Newtonsoft.Json;  
  
var builder = WebApplication.CreateBuilder(args);  
  
// Add services to the container.  
  
builder.Services.AddControllers();  
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle  
builder.Services.AddEndpointsApiExplorer();  
builder.Services.AddSwaggerGen();  
builder.Services.AddRequestTimeouts();  
  
var app = builder.Build();  
  
// Configure the HTTP request pipeline.  
if (app.Environment.IsDevelopment())  
{  
    app.UseSwagger();  
    app.UseSwaggerUI();  
}  
  
app.UseAuthorization();  
app.UseRequestTimeouts();  
app.MapControllers();  
  
app.Run();

现在,让我们看看如何配置终结点,以便为 Web API 和最小 API 设置 RequestTimeouts。

[HttpGet("twosecondtimeout/{waitSeconds:int}")]
[RequestTimeout(2000)]
public async Task<IActionResult> GetCustomerWithTwoSecondTimeoutAsync([FromRoute] int waitSeconds)
{
  await Task.Delay(TimeSpan.FromSeconds(waitSeconds), HttpContext.RequestAborted);
  return Ok();
}
app.MapGet("/twosecondtimeout/{waitSeconds:int}", async ([FromRoute] int waitSeconds, HttpContext context) =>
{
    await Task.Delay(TimeSpan.FromSeconds(waitSeconds), context.RequestAborted);
    return Results.Ok();
}).WithRequestTimeout(TimeSpan.FromSeconds(2));

当您超过配置的超时时,您将看到 API 返回以下状态代码。

_注意:_当应用程序在调试模式下运行时,超时中间件不会激活。此行为与 Kestrel 超时一致。若要测试超时,请在不附加调试器的情况下运行应用程序 (ctrl + F5)。

现在,让我们深入探讨一些高级选项,例如命名策略、自定义状态代码和自定义响应。

配置命名策略

我们可以定义命名的 RequestTimeout 策略,并使用它来配置端点,如下所示:

builder.Services.AddRequestTimeouts(options => 
{   
    options.AddPolicy("threesecondpolicy", TimeSpan.FromSeconds(3));
});
[HttpGet("threesecondtimeout/{waitSeconds:int}")]
[RequestTimeout("threesecondpolicy")]
public async Task<IActionResult> GetCustomerWithThreeSecondTimeoutPolicyAsync([FromRoute] int waitSeconds)
{
  await Task.Delay(TimeSpan.FromSeconds(waitSeconds), HttpContext.RequestAborted);
  return Ok();
}
app.MapGet("/threesecondtimeout/{waitSeconds:int}", async ([FromRoute] int waitSeconds, HttpContext context) =>
{
    await Task.Delay(TimeSpan.FromSeconds(waitSeconds), context.RequestAborted);
    return Results.Ok();
}).WithRequestTimeout("threesecondpolicy");

配置自定义状态代码

在定义策略时,我们可以定义要返回的自定义状态代码,如下所示:

builder.Services.AddRequestTimeouts(options => 
{
    options.AddPolicy("customstatuscode", new RequestTimeoutPolicy 
    {
        Timeout = TimeSpan.FromSeconds(3),
        TimeoutStatusCode = 503
    });
});
[HttpGet("customstatuscode/{waitSeconds:int}")]
[RequestTimeout("customstatuscode")]
public async Task<IActionResult> GetCustomerWithCustomStatusCodePolicyAsync([FromRoute] int waitSeconds)
{
    await Task.Delay(TimeSpan.FromSeconds(waitSeconds), HttpContext.RequestAborted);
    return Ok();
}
app.MapGet("/customstatuscode/{waitSeconds:int}", [RequestTimeout("customstatuscode")] async ([FromRoute] int waitSeconds, HttpContext context) =>
{
    await Task.Delay(TimeSpan.FromSeconds(waitSeconds), context.RequestAborted);
    return Results.Ok();
});

当您的请求超时超过配置的超时时,我们可以看到 API 返回配置的状态代码。

配置自定义委托以自定义响应

在定义策略时,我们可以定义自定义委托来自定义返回响应,如下所示:

builder.Services.AddRequestTimeouts(options => 
{
    options.AddPolicy("customdelegatepolicy", new RequestTimeoutPolicy
    {
        Timeout = TimeSpan.FromSeconds(3),
        TimeoutStatusCode = 503,
        WriteTimeoutResponse = async (HttpContext context) => {
            context.Response.ContentType = "application/json";
            var errorResponse = new
            {
                error = "Request time out from custome delegate policy",
                status = 503
            };
            var jsonResponse = JsonConvert.SerializeObject(errorResponse);
            await context.Response.WriteAsync(jsonResponse);
        }
    });
});
[HttpGet("customdelegatepolicy/{waitSeconds:int}")]
[RequestTimeout("customdelegatepolicy")]
public async Task<IActionResult> GetCustomerWithCustomDelegateAsync([FromRoute] int waitSeconds)
{
    await Task.Delay(TimeSpan.FromSeconds(waitSeconds), HttpContext.RequestAborted);
    return Ok();
}
app.MapGet("/customdelegatepolicy/{waitSeconds:int}", async ([FromRoute] int waitSeconds, HttpContext context) =>
{
    await Task.Delay(TimeSpan.FromSeconds(waitSeconds), context.RequestAborted);
    return Results.Ok();
}).WithRequestTimeout("customdelegatepolicy");

当您的请求超时超过配置的超时时,我们可以看到 API 返回以下响应。

全局默认请求超时策略

就像我们在每个端点定义策略和配置策略的方式一样,我们可以将全局超时策略定义为捕获所有策略,如下所示:

builder.Services.AddRequestTimeouts(options =>   
{  
    options.DefaultPolicy = new RequestTimeoutPolicy  
    {  
        Timeout = TimeSpan.FromMilliseconds(1500)  
    };  
    options.AddPolicy("threesecondpolicy", TimeSpan.FromSeconds(3));  
    options.AddPolicy("customstatuscode", new RequestTimeoutPolicy   
    {  
        Timeout = TimeSpan.FromSeconds(3),  
        TimeoutStatusCode = 503  
    });  
    options.AddPolicy("customdelegatepolicy", new RequestTimeoutPolicy  
    {  
        Timeout = TimeSpan.FromSeconds(3),  
        TimeoutStatusCode = 503,  
        WriteTimeoutResponse = async (HttpContext context) => {  
            context.Response.ContentType = "application/json";  
            var errorResponse = new  
            {  
                error = "Request time out from custome delegate policy",  
                status = 503  
            };  
            var jsonResponse = JsonConvert.SerializeObject(errorResponse);  
            await context.Response.WriteAsync(jsonResponse);  
        }  
    });  
});

禁用请求超时

配置全局默认超时策略后,所有终结点都将使用该策略强制执行,但在某些情况下,我们可能需要排除某些终结点应用该策略。我们可以使用 DisableRequestTimeout 属性来实现这一点,如下所示:

[HttpGet("disableTimeout/{waitSeconds:int}")]
[DisableRequestTimeout]
public async Task<IActionResult> GetCustomerWithNoTimeoutAsync([FromRoute] int waitSeconds)
{
    await Task.Delay(TimeSpan.FromSeconds(waitSeconds), HttpContext.RequestAborted);
    return Ok();
}
app.MapGet("/disablerequestTimeout/{waitSeconds:int}", async ([FromRoute] int waitSeconds, HttpContext context) =>
{
    await Task.Delay(TimeSpan.FromSeconds(waitSeconds), context.RequestAborted);
    return Results.Ok();
}).DisableRequestTimeout();

我们在这篇博客中介绍了有关请求超时中间件的所有内容。我们将在以后的博客中介绍有关 .NET Web API 的更多主题。

源代码获取:公众号回复消息【code:46036

相关代码下载地址
重要提示!:取消关注公众号后将无法再启用回复功能,不支持解封!
第一步:微信扫码关键公众号“架构师老卢”
第二步:在公众号聊天框发送code:46036,如:code:46036 获取下载地址
第三步:恭喜你,快去下载你想要的资源吧
阅读排行