Uzun süreli bağlantı
Sunucudan Gönderilen Olaylar (SSE) uzun süredir devam eden bir HTTP bağlantısı ** olduğundan, yeni başlayanlar için buna ihtiyacımız var:
proxy_http_version 1.1;
proxy_set_header Connection "";
NOT: HTTP / 1.1'deki TCP bağlantıları varsayılan olarak kalıcıdır, bu nedenle Bağlantı başlığını boş olarak ayarlamak doğru olanı yapar ve Nginx önerisidir.
Yığınlı Kodlama
Şimdi bir kenara; SSE yanıtları bir İçerik Uzunluğu üstbilgisi ayarlamaz, çünkü ne kadar verinin gönderileceğini bilemezler, bunun yerine gerçek zamanlı aktarım bağlantısına izin veren Aktarım Kodlaması üstbilgisini [0] [1] kullanmaları gerekir. Ayrıca dikkat: İçerik Uzunluğu eklemezseniz HTTP sunucularının çoğu Transfer-Encoding: chunked;
sizin için ayarlanır . Garip bir şekilde, HTTP yığınları uyarıldı ve karışıklığa neden oldu.
Karışıklık, W3 EventSource açıklamasının Notlar bölümünde biraz belirsiz bir uyarıdan kaynaklanıyor:
Yazarlar ayrıca HTTP yığınının bu protokolün güvenilirliği üzerinde beklenmedik olumsuz etkileri olabileceği konusunda da uyarılmaktadır. Mümkün olduğunda, mesajların oranı bunun için önemli olmayacak kadar yüksek olmadıkça, olay akışları sunmak için parçalama devre dışı bırakılmalıdır.
Birinin Transfer-Encoding: chunked;
SSE için kötü bir şey olduğuna inanmasına neden olur . Ancak, durum böyle değildir, bu sadece web sunucunuz sizin için parçalama yaparken (verileriniz hakkında bilgi bilmeden) bir sorundur. Bu nedenle, çoğu yazı chunked_transfer_encoding off;
tipik durumda bunun eklenmesini önermeyecek olsa da [3].
Tamponlama (asıl sorun)
Çoğu sorunun nereden geldiği, uygulama sunucusu ile istemci arasında herhangi bir arabelleğe alma işlemidir. Varsayılan [4], Nginx kullanımlara göre
proxy_buffering on
(aynı zamanda bir göz atın uwsgi_buffering
ve fastcgi_buffering
uygulamanıza bağlı olarak) ve size müşteriye çıkmak istiyorum parçalarını tampon tercih edebilir. Bu kötü bir şey çünkü SSE'nin gerçek zamanlı doğası kırılıyor.
Ancak, proxy_buffering off
her şey için çevirmek yerine, X-Accel-Buffering: no
uygulamanızdan gelen tüm yanıtlar için yalnızca SSE tabanlı yanıt için arabelleğe almayı kapatmak üzere uygulama sunucusu kodunuza bir yanıt başlığı olarak eklemek en iyisidir (mümkünse). sunucusu. Bonus: Bu uwsgi
ve için de işe yarar fastcgi
.
Çözüm
Ve gerçekten önemli ayarlar aslında uygulama sunucusu yanıt başlıklarıdır:
Content-Type: text/event-stream;
Cache-Control: no-cache;
X-Accel-Buffering: no;
Ve potansiyel olarak bazı ping mekanizmasının uygulanması, böylece bağlantı çok uzun süre boşta kalmaz. Bunun tehlikesi, Nginx'in rölanti bağlantılarını ayar kullanılarak ayarlandığı şekilde kapatmasıdır keepalive
.
[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-eventsource-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