Sunucudan Gönderilen Olaylar (SSE) için hangi Nginx proxy yapılandırması uygundur?


21

Nginx yapılandırmasının SSE için neyin uygun olduğuna dair bir dizi farklı soru okudum ve hangi ayarların kullanılacağına dair kafa karıştırıcı bazı sonuçlar elde ettim:

Peki doğru cevap nedir?

Yanıtlar:


46

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_bufferingve fastcgi_bufferinguygulamanı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 offher şey için çevirmek yerine, X-Accel-Buffering: nouygulamanı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 uwsgive 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


Ping mekanizmasının ne olduğunu açıklayabilir misiniz? Sadece kanala boş bir mesaj mı iletiyor? Nginx ve uygulama düzeyi üstbilgilerini ayarladım, ancak yine de olay kaynağı uç noktalarından herhangi biri için nginx'ten 504 zaman aşımı alıyorum.
wgwz

ping, bağlantı üzerinden belirli aralıklarla gönderilen bazı (sahte) veriler olacaktır, istemcide bu ping'i işleyebilir ve yok sayabilirsiniz. NOT: bağlantınız hiç çalışmıyorsa, ping işlemi yardımcı olmaz, başka bir şey yanlıştır.
c4urself

2
Yanıt başlıklarını önerildiği gibi ekledim ve işe yarıyor. Ben nginx v1.12 config hiçbir değişiklik yapmadım ve şimdiye kadar hiçbir sorun.
Mikkel

1
X-Accel-Buffering: noÜstbilgi eklemek benim için önemliydi, ama en önemlisi, @ c4urself yazdığı gibi yapmak zorunda kaldım: "X-Accel-Buffering ekleyin: hayır uygulama sunucusu kodunuzda bir yanıt başlığı olarak ". Bu üstbilgiyi nginx yapılandırmamdaki bir konum bölümüne eklemek işe yaramadı - tüm olay akışı, uygulama bittikten / sonlandırılana kadar gönderilmeyi bekledi.
MDMower

proxy_http_version 1.1; gerekli? Bir tarayıcıdan 6'dan fazla SSE akışı çalıştırmaya çalışıyorum ve bu nedenle HTTP2'ye ihtiyacım var.
Bilal Fazlani
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.