Timeout yêu cầu trong YARP (YARP Request Timeouts)
Nguồn: YARP Request Timeouts
Giới thiệu
.NET 8 đã giới thiệu Request Timeouts Middleware để cho phép cấu hình timeout (thời gian chờ) yêu cầu toàn cục cũng như theo từng endpoint. Chức năng này cũng có sẵn trong YARP 2.1 khi chạy trên .NET 8 trở lên.
Mặc định
Các yêu cầu không có bất kỳ timeout nào theo mặc định, ngoài ActivityTimeout (thời gian chờ hoạt động) được sử dụng để dọn dẹp các yêu cầu nhàn rỗi. Một policy mặc định được chỉ định trong RequestTimeoutOptions sẽ áp dụng cho các yêu cầu được proxy.
Tương tác với ActivityTimeout
Cả Timeout ở cấp route và ActivityTimeout ở cấp cluster đều áp dụng cho các yêu cầu được proxy. Hiểu cách chúng tương tác là quan trọng để cấu hình timeout phù hợp:
- ActivityTimeout được cấu hình cho mỗi cluster trong phần
HttpRequestvà có giá trị mặc định là 100 giây. Timeout này reset bất cứ khi nào có hoạt động trên yêu cầu. Hoạt động bao gồm nhận header phản hồi hoặc đọc/ghi thành công dữ liệu yêu cầu, phản hồi hoặc streaming (như gRPC hoặc WebSocket). TCP keep-alives và HTTP/2 protocol pings không reset timeout, nhưng WebSocket pings thì có. - Timeout được cấu hình cho mỗi route và chỉ định tổng thời gian cho phép để yêu cầu hoàn thành.
Timeout nào được ưu tiên?
Cả hai timeout đều được áp dụng đồng thời. Nếu yêu cầu nhàn rỗi (không có hoạt động), ActivityTimeout sẽ hủy nó. Nếu yêu cầu đang hoạt động nhưng mất quá nhiều thời gian tổng thể, Timeout ở cấp route sẽ hủy nó. Trong thực tế, với một yêu cầu nhàn rỗi, timeout nào thấp hơn sẽ có hiệu lực trước.
Ví dụ:
- Với
Timeoutcủa route là 300 giây vàActivityTimeoutmặc định 100 giây: nếu yêu cầu trở nên nhàn rỗi, nó sẽ bị hủy sau 100 giây doActivityTimeout, mặc dù route cho phép đến 300 giây. - Với
Timeoutcủa route là 60 giây vàActivityTimeoutmặc định 100 giây: yêu cầu sẽ bị hủy sau 60 giây nếu chưa hoàn thành, bất kể hoạt động.
Lưu ý khi debug
Một sự khác biệt quan trọng giữa hai timeout này:
- Timeout ở cấp route không áp dụng khi có debugger (trình gỡ lỗi) được đính kèm vào tiến trình, giúp dễ debug các yêu cầu chạy dài.
- ActivityTimeout luôn áp dụng, kể cả khi debugger được đính kèm.
Để tránh ActivityTimeout ảnh hưởng đến việc debug hoặc các yêu cầu chạy dài hợp lệ, hãy cấu hình rõ ràng trong phần HttpRequest của cluster:
{
"Clusters": {
"cluster1": {
"HttpRequest": {
"ActivityTimeout": "00:10:00"
},
"Destinations": {
"cluster1/destination1": {
"Address": "https://localhost:10001/"
}
}
}
}
}Cấu hình
Timeout và Timeout Policy có thể được chỉ định cho từng route thông qua RouteConfig và có thể được liên kết từ phần Routes của file cấu hình. Giống như các thuộc tính route khác, điều này có thể được sửa đổi và tải lại mà không cần khởi động lại proxy. Tên policy không phân biệt chữ hoa/thường.
Timeout được chỉ định theo định dạng TimeSpan (HH:MM:SS). Chỉ định cả Timeout lẫn TimeoutPolicy trên cùng một route là không hợp lệ và sẽ khiến cấu hình bị từ chối.
Lưu ý rằng timeout yêu cầu không áp dụng khi debugger được đính kèm vào tiến trình.
Ví dụ:
{
"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/"
}
}
}
}
}
}Các timeout policy và policy mặc định có thể được cấu hình trong service collection (tập hợp dịch vụ) và middleware có thể được thêm vào như sau:
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();Tắt timeout
Chỉ định giá trị disable trong tham số TimeoutPolicy của route có nghĩa là middleware timeout yêu cầu sẽ không áp dụng timeout cho route này.
WebSockets
Timeout yêu cầu bị tắt sau khi WebSocket handshake (bắt tay WebSocket) ban đầu. Tuy nhiên, ActivityTimeout áp dụng cho các yêu cầu WebSocket. WebSocket keep-alives có thể được bật bởi client hoặc server đang giao tiếp với proxy để giữ cho kết nối không bị nhàn rỗi và kích hoạt ActivityTimeout.