Kết nối lâu dài
Sự kiện gửi máy chủ (SSE) là một kết nối HTTP chạy dài **, vì vậy, đối với người mới bắt đầu, chúng tôi cần điều này:
proxy_http_version 1.1;
proxy_set_header Connection "";
LƯU Ý: Theo mặc định, các kết nối TCP trong HTTP / 1.1 vẫn tồn tại, do đó, đặt tiêu đề Kết nối thành trống sẽ là điều đúng đắn và là gợi ý Nginx.
Chunked chuyển mã hóa
Bây giờ là một bên; Phản hồi SSE không đặt tiêu đề Độ dài nội dung vì họ không thể biết lượng dữ liệu sẽ được gửi, thay vào đó họ cần sử dụng tiêu đề Mã hóa chuyển [0] [1], cho phép kết nối truyền phát. Cũng lưu ý: nếu bạn không thêm Độ dài nội dung, hầu hết các máy chủ HTTP sẽ đặt Transfer-Encoding: chunked;
cho bạn. Kỳ lạ thay, HTTP chunking cảnh báo chống lại và gây nhầm lẫn.
Sự nhầm lẫn bắt nguồn từ một cảnh báo hơi mơ hồ trong phần Ghi chú của mô tả W3 EventSource:
Các tác giả cũng được cảnh báo rằng việc phân chia HTTP có thể có những tác động tiêu cực không mong muốn đối với độ tin cậy của giao thức này. Nếu có thể, chunking nên bị vô hiệu hóa để phục vụ các luồng sự kiện trừ khi tỷ lệ tin nhắn đủ cao để điều này không thành vấn đề.
Điều đó sẽ khiến người ta tin rằng đó Transfer-Encoding: chunked;
là một điều tồi tệ đối với SSE. Tuy nhiên: điều này không nhất thiết phải như vậy, nó chỉ là vấn đề khi máy chủ web của bạn đang làm việc với bạn (không biết thông tin về dữ liệu của bạn). Vì vậy, trong khi hầu hết các bài viết sẽ đề xuất thêm chunked_transfer_encoding off;
điều này là không cần thiết trong trường hợp điển hình [3].
Bộ đệm (vấn đề thực sự)
Trường hợp hầu hết các vấn đề đến từ việc có bất kỳ loại bộ đệm nào giữa máy chủ ứng dụng và máy khách. Theo mặc định [4], Nginx sử dụng
proxy_buffering on
(cũng hãy xem uwsgi_buffering
và fastcgi_buffering
tùy thuộc vào ứng dụng của bạn) và có thể chọn để đệm các đoạn mà bạn muốn thoát ra cho khách hàng của mình. Đây là một điều xấu vì bản chất thời gian thực của SSE bị phá vỡ.
Tuy nhiên, thay vì bật proxy_buffering off
mọi thứ, thực sự tốt nhất (nếu bạn có thể) thêm X-Accel-Buffering: no
tiêu đề làm phản hồi trong mã máy chủ ứng dụng của mình để chỉ tắt bộ đệm cho phản hồi dựa trên SSE chứ không phải cho tất cả các phản hồi đến từ ứng dụng của bạn người phục vụ. Tiền thưởng: điều này cũng sẽ làm việc cho uwsgi
và fastcgi
.
Giải pháp
Và do đó, các cài đặt thực sự quan trọng thực sự là các tiêu đề phản hồi của máy chủ ứng dụng:
Content-Type: text/event-stream;
Cache-Control: no-cache;
X-Accel-Buffering: no;
Và có khả năng thực hiện một số cơ chế ping để kết nối không ở trạng thái quá lâu. Điều nguy hiểm của điều này là Nginx sẽ đóng các kết nối nhàn rỗi như được đặt bằng cách sử dụng keepalive
cài đặt.
[0] https://tools.ietf.org/html/rfc2616#section-3.6
[1] https://en.wikipedia.org/wiki/Chunked_transfer_encoding
[2] https://www.w3.org/TR / 2009 / WD-eventource-20091029 / # text-event-stream
[3] https://github.com/whatwg/html/issues/515
[4] http://nginx.org/en/docs/http/ ngx_http_proxy_module.html # proxy_buffering
[5] https://tools.ietf.org/html/rfc7230#section-6.3
[6] https://gist.github.com/CMCDragonkai/6bfade6431e9ffb7fe88