web-dev-qa-db-ja.com

Nginxを介したEventSource /サーバー送信イベント

streamブロックでSinatraを使用するサーバー側。

get '/stream', :provides => 'text/event-stream' do
  stream :keep_open do |out|
    connections << out
    out.callback { connections.delete(out) }
  end
end

クライアント側:

var es = new EventSource('/stream');
es.onmessage = function(e) { $('#chat').append(e.data + "\n") };

http://localhost:9292/経由でアプリを直接使用すると、すべてが完璧に機能します。接続は永続的であり、すべてのメッセージはすべてのクライアントに渡されます。

ただし、Nginx、http://chat.devを通過すると、接続はドロップされ、1秒ごとに再接続が発生します。

Nginxのセットアップは私には問題ないようです:

upstream chat_dev_upstream {
  server 127.0.0.1:9292;
}

server {
  listen       80;
  server_name  chat.dev;

  location / {
    proxy_pass http://chat_dev_upstream;
    proxy_buffering off;
    proxy_cache off;
    proxy_set_header Host $Host;
  }
}

keepalive 1024 in upstreamセクションと同様にlocationセクションでproxy_set_header Connection keep-alive;を試しました。

何も助けません:(

クライアントに渡されない永続的な接続とメッセージはありません。

63
Lukas Mayer

Nginxの設定が正しいので、数行見逃しているだけです。

NginxでEventSourceを機能させる「魔法のトリオ」を次に示します。

proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;

それらをlocationセクションに配置すると、動作するはずです。

追加する必要がある場合もあります

proxy_buffering off;
proxy_cache off;

それは公式の方法ではありません。

私は「試行錯誤」+「グーグル」でこれで終わった:)

143
user904990

別のオプションは、応答に値「no」の「X-Accel-Buffering」ヘッダーを含めることです。 Nginxはそれを特別に扱います。 http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering を参照してください。

6
E1.

これを自分で最初から書いてはいけません。 Nginxは素晴らしいイベントサーバーであり、アップストリームサーバーのパフォーマンスを低下させることなくSSEを処理するモジュールを備えています。

チェックアウト https://github.com/wandenberg/nginx-Push-stream-module

動作方法は、サブスクライバー(SSEを使用するブラウザー)がNginxに接続し、接続がそこで停止することです。パブリッシャー(Nginxの背後にあるサーバー)は、対応するルートでPOSTをNginxに送信し、その瞬間にNginxはブラウザーの待機中のEventSourceリスナーに転送します。

この方法は、Ruby webserverがこれらの「長いポーリング」を処理するよりもはるかにスケーラブルですSSE接続。

5
Martin Konecny