Thoát Request (Request Draining) với máy chủ web Kestrel trong ASP.NET Core
Việc mở kết nối HTTP tốn thời gian. Với HTTPS, nó còn tốn tài nguyên. Do đó, Kestrel cố gắng tái sử dụng kết nối theo giao thức HTTP/1.1. Phần thân của request phải được đọc đầy đủ để cho phép kết nối được tái sử dụng. Ứng dụng không phải lúc nào cũng tiêu thụ phần thân của request, chẳng hạn như các request HTTP POST mà server trả về redirect (chuyển hướng) hoặc phản hồi 404. Trong trường hợp HTTP POST redirect:
- Client có thể đã gửi một phần dữ liệu POST.
- Server ghi phản hồi 301.
- Kết nối không thể được dùng cho request mới cho đến khi dữ liệu POST từ phần thân request trước đã được đọc đầy đủ.
- Kestrel cố gắng thoát (drain) phần thân request. Thoát phần thân request nghĩa là đọc và loại bỏ dữ liệu mà không xử lý nó.
Quá trình thoát thực hiện sự đánh đổi giữa việc cho phép kết nối được tái sử dụng và thời gian cần thiết để thoát hết dữ liệu còn lại:
- Quá trình thoát có timeout (thời gian chờ) là năm giây, không thể cấu hình.
- Nếu tất cả dữ liệu được chỉ định bởi header
Content-LengthhoặcTransfer-Encodingchưa được đọc trước khi hết timeout, kết nối sẽ bị đóng.
Đôi khi bạn có thể muốn chấm dứt request ngay lập tức, trước hoặc sau khi ghi phản hồi. Ví dụ, client có thể có giới hạn dữ liệu nghiêm ngặt. Giới hạn dữ liệu được tải lên có thể là ưu tiên. Trong những trường hợp như vậy để chấm dứt request, hãy gọi HttpContext.Abort từ controller, Razor Page, hoặc middleware.
Có một số lưu ý khi gọi Abort:
- Tạo kết nối mới có thể chậm và tốn kém.
- Không có gì đảm bảo rằng client đã đọc phản hồi trước khi kết nối bị đóng.
- Gọi
Abortnên hiếm gặp và chỉ dành cho các trường hợp lỗi nghiêm trọng, không phải lỗi thông thường. - Chỉ gọi
Abortkhi cần giải quyết một vấn đề cụ thể. Ví dụ, gọiAbortnếu client độc hại đang cố gắng POST dữ liệu hoặc khi có lỗi trong code client gây ra các request lớn hoặc nhiều request. - Không gọi
Abortcho các tình huống lỗi thông thường, chẳng hạn như HTTP 404 (Not Found - Không tìm thấy).
Gọi HttpResponse.CompleteAsync trước khi gọi Abort đảm bảo rằng server đã hoàn thành việc ghi phản hồi. Tuy nhiên, hành vi của client không thể đoán trước và client có thể không đọc phản hồi trước khi kết nối bị hủy.
Quá trình này khác với HTTP/2 vì giao thức hỗ trợ hủy bỏ các luồng request riêng lẻ mà không đóng kết nối. Timeout thoát năm giây không áp dụng. Nếu có bất kỳ dữ liệu phần thân request chưa đọc nào sau khi hoàn thành phản hồi, thì server gửi một HTTP/2 RST frame. Các data frame phần thân request bổ sung bị bỏ qua.
Nếu có thể, tốt hơn cho client nên sử dụng header request Expect: 100-continue và chờ server phản hồi trước khi bắt đầu gửi phần thân request. Điều đó cho client cơ hội kiểm tra phản hồi và hủy bỏ trước khi gửi dữ liệu không cần thiết.