ASP.NET Core 中的请求超时中间件 您所在的位置:网站首页 uniapp请求超时 ASP.NET Core 中的请求超时中间件

ASP.NET Core 中的请求超时中间件

2023-05-06 22:07| 来源: 网络整理| 查看: 265

应用可以选择性地对请求应用超时限制。 ASP.NET Core服务器默认不执行此操作,因为请求处理时间因方案而异。 例如,WebSocket、静态文件和调用昂贵的 API 都需要不同的超时限制。 因此,ASP.NET Core提供了中间件,用于配置每个终结点的超时以及全局超时。

达到超时限制时, CancellationToken 中的 HttpContext.RequestAborted 已 IsCancellationRequested 设置为 true。 请求不会自动中止。 由应用检查RequestAborted并决定如何处理超时。

本文介绍如何配置超时中间件。 超时中间件可用于所有类型的 ASP.NET Core应用:最小 API、带控制器的 Web API、MVC 和 Razor Pages。 示例应用是一个最小 API,但它演示的每个超时功能在其他应用类型中也受支持。

请求超时位于 命名空间中 Microsoft.AspNetCore.Http.Timeouts 。

将中间件添加到应用

通过调用 AddRequestTimeouts将请求超时中间件添加到服务集合。

通过调用 UseRequestTimeouts将中间件添加到请求处理管道。

注意

在显式调用 UseRouting的应用中, UseRequestTimeouts 必须在 之后 UseRouting调用 。

将中间件添加到应用不会自动开始触发超时。 必须显式配置超时限制。

配置一个终结点或页面

对于最小 API 应用,请通过调用 WithRequestTimeout或应用 [RequestTimeout] 属性将终结点配置为超时,如以下示例所示:

using Microsoft.AspNetCore.Http.Timeouts; var builder = WebApplication.CreateBuilder(args); builder.Services.AddRequestTimeouts(); var app = builder.Build(); app.UseRequestTimeouts(); app.MapGet("/", async (HttpContext context) => { await Task.Delay(TimeSpan.FromSeconds(2)); if (context.RequestAborted.IsCancellationRequested) { return Results.Content("Timeout!", "text/plain"); } return Results.Content("No timeout!", "text/plain"); }).WithRequestTimeout(TimeSpan.FromSeconds(1)); // Returns "Timeout!" app.MapGet("/attribute", [RequestTimeout(milliseconds: 1000)] async (HttpContext context) => { await Task.Delay(TimeSpan.FromSeconds(2)); if (context.RequestAborted.IsCancellationRequested) { return Results.Content("Timeout!", "text/plain"); } return Results.Content("No timeout!", "text/plain"); }); // Returns "Timeout!" app.Run();

对于具有控制器的应用,将 [RequestTimeout] 属性应用于操作方法或控制器类。 对于 Razor Pages 应用,将 属性应用于 Razor 页面类。

配置多个终结点或页面

创建命名 策略 以指定应用于多个终结点的超时配置。 通过调用 AddPolicy添加策略:

builder.Services.AddRequestTimeouts(options => { options.DefaultPolicy = new RequestTimeoutPolicy { Timeout = TimeSpan.FromMilliseconds(1500) }; options.AddPolicy("MyPolicy", TimeSpan.FromSeconds(1)); });

可以按策略名称为终结点指定超时:

app.MapGet("/namedpolicy", async (HttpContext context) => { await Task.Delay(TimeSpan.FromSeconds(2)); if (context.RequestAborted.IsCancellationRequested) { return Results.Content("Timeout!", "text/plain"); } return Results.Content("No timeout!", "text/plain"); }).WithRequestTimeout("MyPolicy"); // Returns "Timeout!"

属性 [RequestTimeout] 还可用于指定命名策略。

设置全局默认超时策略

为全局默认超时配置指定策略:

builder.Services.AddRequestTimeouts(options => { options.DefaultPolicy = new RequestTimeoutPolicy { Timeout = TimeSpan.FromMilliseconds(1500) }; options.AddPolicy("MyPolicy", TimeSpan.FromSeconds(1)); });

默认超时适用于未指定超时的终结点。 以下终结点代码检查超时,尽管它不调用扩展方法或应用 属性。 全局超时配置适用,因此代码会检查超时:

app.MapGet("/", async (HttpContext context) => { await Task.Delay(TimeSpan.FromSeconds(2)); if (context.RequestAborted.IsCancellationRequested) { return Results.Content("Timeout!", "text/plain"); } return Results.Content("No timeout!", "text/plain"); }); // Returns "Timeout!" due to default policy. 在策略中指定状态代码

类 RequestTimeoutPolicy 具有属性,该属性可以在触发超时时自动设置状态代码。

builder.Services.AddRequestTimeouts(options => { options.DefaultPolicy = new RequestTimeoutPolicy { Timeout = TimeSpan.FromMilliseconds(1000), TimeoutStatusCode = 504 }; options.AddPolicy("MyPolicy2", new RequestTimeoutPolicy { Timeout = TimeSpan.FromMilliseconds(1000), WriteTimeoutResponse = async (HttpContext context) => { context.Response.ContentType = "text/plain"; await context.Response.WriteAsync("Timeout!"); } }); }); app.MapGet("/", async (HttpContext context) => { await Task.Delay(TimeSpan.FromSeconds(2)); context.RequestAborted.ThrowIfCancellationRequested(); return Results.Content("No timeout!", "text/plain"); }); // Returns status code 504 due to default policy. 在策略中使用委托

类 RequestTimeoutPolicy 具有属性 WriteTimeoutResponse ,该属性可用于在触发超时时自定义响应。

builder.Services.AddRequestTimeouts(options => { options.DefaultPolicy = new RequestTimeoutPolicy { Timeout = TimeSpan.FromMilliseconds(1000), TimeoutStatusCode = 504 }; options.AddPolicy("MyPolicy2", new RequestTimeoutPolicy { Timeout = TimeSpan.FromMilliseconds(1000), WriteTimeoutResponse = async (HttpContext context) => { context.Response.ContentType = "text/plain"; await context.Response.WriteAsync("Timeout!"); } }); }); app.MapGet("/usepolicy2", async (HttpContext context) => { await Task.Delay(TimeSpan.FromSeconds(2)); context.RequestAborted.ThrowIfCancellationRequested(); return Results.Content("No timeout!", "text/plain"); }).WithRequestTimeout("MyPolicy2"); // Returns "Timeout!" due to WriteTimeoutResponse in MyPolicy2. 禁用超时

若要禁用包括默认全局超时在内的所有超时,请使用 [DisableRequestTimeout] 属性或 DisableRequestTimeout 扩展方法:

app.MapGet("/disablebyattr", [DisableRequestTimeout] async (HttpContext context) => { await Task.Delay(TimeSpan.FromSeconds(2)); return Results.Content("No timeout!", "text/plain"); }); // Returns "No timeout!", ignores default timeout. app.MapGet("/disablebyext", async (HttpContext context) => { await Task.Delay(TimeSpan.FromSeconds(2)); return Results.Content("No timeout!", "text/plain"); }).DisableRequestTimeout(); // Returns "No timeout!", ignores default timeout. 取消超时

若要取消已启动的超时,请在 上使用 DisableTimeout()IHttpRequestTimeoutFeature方法。 超时在过期后无法取消。

app.MapGet("/canceltimeout", async (HttpContext context) => { var timeoutFeature = context.Features.Get(); timeoutFeature?.DisableTimeout(); await Task.Delay(TimeSpan.FromSeconds(2)); if (context.RequestAborted.IsCancellationRequested) // is false { } return Results.Content("No timeout!", "text/plain"); }).WithRequestTimeout(TimeSpan.FromSeconds(1)); // Returns "No timeout!" since the default timeout is not triggered. 另请参阅 Microsoft.AspNetCore.Http.Timeouts ASP.NET Core 中间件


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有