Długotrwałe połączenie
Zdarzenia wysyłane przez serwer (SSE) to długotrwałe połączenie HTTP **, więc na początek potrzebujemy tego:
proxy_http_version 1.1;
proxy_set_header Connection "";
UWAGA: Połączenia TCP w HTTP / 1.1 są domyślnie trwałe, więc ustawienie pustego nagłówka połączenia robi właściwą rzecz i jest sugestią Nginx.
Chunked Transfer-Encoding
Teraz na bok; Odpowiedzi SSE nie ustawiają nagłówka Content-Length, ponieważ nie mogą wiedzieć, ile danych zostanie wysłanych, zamiast tego muszą użyć nagłówka Transfer-Encoding [0] [1], co pozwala na połączenie strumieniowe. Uwaga: jeśli nie dodasz długości treści, większość serwerów HTTP zostanie Transfer-Encoding: chunked;dla Ciebie ustawiona . O dziwo, fragmentowanie HTTP ostrzegało i powoduje zamieszanie.
Zamieszanie wynika z nieco niejasnego ostrzeżenia w sekcji Notatki opisu W3 EventSource:
Ostrzega się także autorów, że dzielenie HTTP może mieć nieoczekiwany negatywny wpływ na niezawodność tego protokołu. Tam, gdzie to możliwe, dzielenie na fragmenty powinno być wyłączone w celu obsługi strumieni zdarzeń, chyba że szybkość wiadomości jest wystarczająco wysoka, aby nie miało to znaczenia.
Co mogłoby prowadzić do przekonania, że Transfer-Encoding: chunked;jest to złe dla SSE. Jednak: niekoniecznie tak jest, jest to tylko problem, gdy twój serwer wykonuje za ciebie części (nie znając informacji o twoich danych). Chociaż większość postów sugeruje, że dodanie chunked_transfer_encoding off;tego nie jest konieczne w typowym przypadku [3].
Buforowanie (prawdziwy problem)
Większość problemów wynika z buforowania między serwerem aplikacji a klientem. Domyślnie [4], wykorzystuje nginx
proxy_buffering on(również przyjrzeć uwsgi_bufferingi fastcgi_bufferingw zależności od aplikacji), a może zdecydować się na kawałki buforować że chcesz wyjść do klienta. Jest to zła rzecz, ponieważ psuje się charakter SSE w czasie rzeczywistym.
Jednak zamiast zwracać się proxy_buffering offo wszystko, najlepiej jest (jeśli możesz) dodać X-Accel-Buffering: nonagłówek odpowiedzi w kodzie serwera aplikacji, aby wyłączyć buforowanie tylko dla odpowiedzi opartej na SSE, a nie dla wszystkich odpowiedzi pochodzących z aplikacji serwer. Bonus: będzie to również działać dla uwsgii fastcgi.
Rozwiązanie
Tak więc naprawdę ważnymi ustawieniami są nagłówki odpowiedzi serwera aplikacji:
Content-Type: text/event-stream;
Cache-Control: no-cache;
X-Accel-Buffering: no;
I potencjalnie implementacja jakiegoś mechanizmu pingowania, aby połączenie nie pozostawało zbyt długo bezczynne. Niebezpieczeństwo polega na tym, że Nginx zamyka bezczynne połączenia zgodnie z keepaliveustawieniem.
[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