SSE (Server-Sent Events)의 경우 어떤 Nginx 프록시 구성이 적합합니까?


답변:


45

장기 연결

SSE (Server-Sent Events)는 오래 실행되는 HTTP 연결 **이므로 초보자에게는 다음이 필요합니다.

proxy_http_version 1.1;
proxy_set_header Connection "";

참고 : HTTP / 1.1의 TCP 연결은 기본적으로 영구적이므로 연결 헤더를 비워두면 올바른 작업이며 Nginx 제안입니다.

청크 전송 인코딩

이제 제쳐두고; SSE 응답은 전송할 데이터 양을 알 수 없기 때문에 Content-Length 헤더를 설정하지 않습니다. 대신 스트리밍 연결을 허용하는 Transfer-Encoding 헤더 [0] [1]를 사용해야합니다. 참고 : Content-Length를 추가하지 않으면 대부분의 HTTP 서버가 설정 Transfer-Encoding: chunked;됩니다. 이상하게도 HTTP 청크는 경고하고 혼란을 야기합니다.

혼란은 W3 EventSource 설명의 Notes 섹션에서 다소 모호한 경고로 인해 발생합니다.

저자는 HTTP 청킹이이 프로토콜의 신뢰성에 예기치 않은 부정적인 영향을 미칠 수 있음을주의해야합니다. 가능한 경우 메시지 속도가 중요하지 않은 경우를 제외하고 이벤트 스트림을 제공하기 위해 청킹을 비활성화해야합니다.

Transfer-Encoding: chunked;SSE에게는 나쁜 일 이라고 믿게 될 것입니다. 그러나 이것은 반드시 그런 것은 아니며 웹 서버가 청크를 수행 할 때만 발생합니다 (데이터에 대한 정보를 모름). 따라서 대부분의 게시물은 chunked_transfer_encoding off;일반적인 경우에는 추가 할 필요가 없다고 제안합니다 [3].

버퍼링 (실제 문제)

대부분의 문제는 앱 서버와 클라이언트 사이에 모든 유형의 버퍼링이 발생합니다. 기본적으로 [4], Nginx에 사용하는함으로써 proxy_buffering on(도에서 살펴 uwsgi_bufferingfastcgi_buffering응용 프로그램에 따라) 당신이 당신의 클라이언트에 나가 원하는 청크를 버퍼링 할 수도 있습니다. SSE의 실시간 특성이 깨지기 때문에 이것은 나쁜 것입니다.

그러나 proxy_buffering off모든 것을 처리하는 대신 실제로 X-Accel-Buffering: noSSE 기반 응답에 대해서만 버퍼링을 해제하고 앱에서 오는 모든 응답에 대해 버퍼링을 해제하려면 애플리케이션 서버 코드에 응답 헤더로 를 추가하는 것이 가장 좋습니다 (가능한 경우). 섬기는 사람. 보너스 :이 또한 위해 작동 uwsgi하고 fastcgi.

해결책

따라서 실제로 중요한 설정은 실제로 앱 서버 응답 헤더입니다.

Content-Type: text/event-stream;
Cache-Control: no-cache;
X-Accel-Buffering: no;

연결이 너무 오랫동안 유휴 상태로 유지되지 않도록 핑 메커니즘을 구현할 가능성이 있습니다. Nginx가 설정을 사용하여 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


핑 메커니즘이 무엇인지 자세히 설명해 주시겠습니까? 단순히 빈 메시지를 채널로 푸시합니까? nginx 및 앱 수준 헤더를 설정했지만 이벤트 소스 끝점에 대해 nginx에서 504 시간 초과가 계속 발생합니다.
wgwz

핑은 연결을 통해 간격을두고 전송 된 일부 (가상) 데이터 일 뿐이며 클라이언트에서이 핑을 처리하고 무시할 수 있습니다. 참고 : 연결이 전혀 작동하지 않으면 핑 (ping)이 도움이되지 않으며 다른 문제가 있습니다.
c4urself

2
제안한대로 응답 헤더를 추가했으며 작동합니다. nginx v1.12 구성을 변경하지 않았으며 지금까지 아무런 문제가 없습니다.
Mikkel

1
X-Accel-Buffering: no헤더를 추가하는 것이 중요했지만, 중요한 것은 @ c4urself가 "X-Accel-Buffering : no를 애플리케이션 서버 코드 의 응답 헤더로 추가"와 같이 작성해야한다는 점 입니다. 내 nginx 설정의 위치 섹션 에이 헤더를 추가해도 작동하지 않았습니다. 응용 프로그램이 종료되거나 종료 될 때까지 전체 이벤트 스트림이 전송되기를 기다렸습니다.
MDMower

proxy_http_version 1.1; 필요? 브라우저에서 6 개 이상의 SSE 스트림을 실행하려고하므로 HTTP2가 필요합니다.
Bilal Fazlani
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.