サーバー送信イベント(SSE)の場合、どのNginxプロキシ構成が適切ですか?


20

Nginxの構成がSSEにどのように適しているかについて、さまざまな質問を読んで、どの設定を使用するかについて混乱を招く結果を導き出しました。

だから正しい答えは何ですか?

回答:


44

長時間の接続

Server-Sent Events(SSE)は長時間実行されるHTTP接続**であるため、初心者にはこれが必要です。

proxy_http_version 1.1;
proxy_set_header Connection "";

注:HTTP / 1.1のTCP接続はデフォルトで永続的であるため、Connectionヘッダーを空に設定することは正しいことであり、Nginxの提案です。

チャンク転送エンコード

余談です。SSE応答は、送信されるデータ量を知ることができないため、Content-Lengthヘッダーを設定しません。代わりに、ストリーミング接続を可能にするTransfer-Encodingヘッダー[0] [1]を使用する必要があります。また、注:Content-Lengthを追加しない場合、ほとんどのHTTPサーバーが設定Transfer-Encoding: chunked;します。奇妙なことに、HTTPチャンキングは警告を発し、混乱を引き起こします。

混乱は、W3 EventSourceの説明のNotesセクションにあるやや曖昧な警告に起因しています。

著者はまた、HTTPチャンクがこのプロトコルの信頼性に予期しない悪影響を与える可能性があることに注意してください。可能であれば、メッセージのレートがこれが問題にならないほど高くない限り、イベントストリームを提供するためにチャンクを無効にする必要があります。

これはTransfer-Encoding: chunked;、SSEにとって悪いことだと考える人を導くでしょう。ただし、これは必ずしもそうではなく、Webサーバーがデータの情報を知らずにチャンクを行っている場合にのみ問題になります。そのため、ほとんどの投稿では追加するよう提案されていchunked_transfer_encoding off;ますが、これは一般的なケースでは必要ありません[3]。

バッファリング(本当の問題)

ほとんどの問題の原因は、アプリサーバーとクライアント間のバッファリングの種類です。デフォルトの[4]で、nginxの用途は proxy_buffering on(も見てみるuwsgi_bufferingfastcgi_buffering、あなたのアプリケーションに応じて)、あなたのクライアントに出たいというチャンクをバッファリングすることもできます。SSEのリアルタイムの性質が壊れているため、これは悪いことです。

ただし、proxy_buffering offすべてを有効にするのではX-Accel-Buffering: noなく、アプリケーションサーバーコードに応答ヘッダーとしてを追加して、アプリケーションからのすべての応答ではなく、SSEベースの応答のバッファリングのみをオフにすることができます(可能な場合)。サーバ。ボーナス:これはuwsgiおよびにも有効ですfastcgi

解決

したがって、本当に重要な設定は、実際にはapp-server応答ヘッダーです。

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

また、接続が長時間アイドル状態にならないように、pingメカニズムを実装する可能性があります。この危険性は、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


pingメカニズムについて詳しく説明できますか?空のメッセージをチャンネルにプッシュするだけですか?nginxとアプリレベルのヘッダーを設定しましたが、イベントソースエンドポイントのいずれかに対して、nginxから504のタイムアウトがまだ発生しています。
wgwz

pingは、接続を介して一定の間隔で送信される(偽の)データであり、クライアントではこのpingを処理して無視できます。注:接続がまったく機能しない場合、pingを実行しても効果はありません。他の何かが間違っています。
c4urself

2
提案どおりに応答ヘッダーを追加しましたが、動作します。私はnginx v1.12の設定に変更を加えておらず、これまでのところ問題はありません。
ミッケル

1
X-Accel-Buffering: noヘッダーを追加することは私にとって重要でしたが、重要なことは、@ c4urselfが書いたように、「X-Accel-Bufferingを追加します。アプリケーションサーバーコードの応答ヘッダーとして」です。このヘッダーをnginx構成の場所セクションに追加しても機能しませんでした-アプリケーションが終了/終了するまで、イベントストリーム全体が送信されるのを待ちました。
MDMower

であるproxy_http_version 1.1; 必要?ブラウザから6つ以上のSSEストリームを実行しようとしているため、HTTP2が必要です。
ビラルファズラニ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.