YARP 请求超时

介绍

.NET 8 引入了请求超时中间件,以便全局以及对每个终结点配置请求超时。 在 .NET 8 或更高版本上运行时,YARP 2.1 中也提供此功能。

默认值

默认情况下,请求不会有任何超时,除了用于清理空闲请求的 ActivityTimeoutRequestTimeoutOptions 中指定的默认策略也适用于代理请求。

与 ActivityTimeout 交互

路由级别 Timeout 和群集级别 ActivityTimeout 都适用于代理请求。 了解交互方式对于正确配置超时非常重要:

  • ActivityTimeout 按分区中的每个 HttpRequest 群集进行配置,默认值为 100 秒。 每当请求上存在活动时,此超时将重置。 活动包括接收响应标头或成功读取或写入请求、响应或流数据(如 gRPC 或 WebSocket)。 TCP 保持活动状态和 HTTP/2 协议的 ping 不会重置超时,但 WebSocket 的 ping 会重置超时。

  • 超时是按每个路由进行配置的,并指定请求完成所允许的总时间。

哪个超时优先?

这两个超时同时适用。 如果请求 处于空闲 状态(无活动),则会 ActivityTimeout 取消请求。 如果请求 处于活动状态 ,但总体耗时过长,则路由级别 Timeout 将取消请求。 实际上,对于空闲请求,超时较短的那个将会先生效。

例如:

  • Timeout路由时间为300 秒,默认值为ActivityTimeout100 秒:如果请求处于空闲状态,则在ActivityTimeout100 秒后将被取消,即使路由允许最多 300 秒。
  • Timeout路由为 60 秒,默认值为 ActivityTimeout100 秒:如果请求尚未完成,则请求将在 60 秒后取消,而不考虑活动。

调试注意事项

这些超时之间的重要区别:

  • 当调试器附加到进程时,路由级超时不适用,因此可以更轻松地调试长时间运行的请求。
  • ActivityTimeout 始终适用,即使附加了调试器。

ActivityTimeout为了避免干扰调试或合法的长时间运行的请求,请在群集的HttpRequest部分中显式配置它:

{
  "Clusters": {
    "cluster1": {
      "HttpRequest": {
        "ActivityTimeout": "00:10:00"
      },
      "Destinations": {
        "cluster1/destination1": {
          "Address": "https://localhost:10001/"
        }
      }
    }
  }
}

配置

可以通过 RouteConfig 为每个路由指定超时和超时策略,并且可以从配置文件的 Routes 部分绑定超时和超时策略。 与其他路由属性一样,无需重启代理即可修改和重新加载此属性。 策略名称不区分大小写。

超时时间以 TimeSpan 格式(HH:MM:SS)指定。 在同一路由上同时指定 Timeout 和 TimeoutPolicy 无效,将导致配置被拒绝。

请注意,当调试器附加到进程时,请求超时不适用。

示例:

{
  "ReverseProxy": {
    "Routes": {
      "route1" : {
        "ClusterId": "cluster1",
        "TimeoutPolicy": "customPolicy",
        "Match": {
          "Hosts": [ "localhost" ]
        }
      }
      "route2" : {
        "ClusterId": "cluster1",
        "Timeout": "00:01:00",
        "Match": {
          "Hosts": [ "localhost2" ]
        }
      }
    },
    "Clusters": {
      "cluster1": {
        "Destinations": {
          "cluster1/destination1": {
            "Address": "https://localhost:10001/"
          }
        }
      }
    }
  }
}

超时策略和默认策略可以在服务集合中配置,并且可以按如下方式添加中间件:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddReverseProxy()
    .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));

builder.Services.AddRequestTimeouts(options =>
{
    options.AddPolicy("customPolicy", TimeSpan.FromSeconds(20));
});

var app = builder.Build();

app.UseRequestTimeouts();

app.MapReverseProxy();

app.Run();

禁用超时

在路由的 disable 参数中指定值 TimeoutPolicy 意味着请求超时中间件不会对此路由应用超时。

WebSocket协议

初始 WebSocket 握手完成后,请求超时会被禁用。 但是, ActivityTimeout 确实适用于 WebSocket 请求。 客户端或服务器可以通过与代理通信来启用 WebSocket 保持连接活动,以防止连接变为空闲状态并触发 ActivityTimeout