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;
を試しました。
何も助けません:(
クライアントに渡されない永続的な接続とメッセージはありません。
Nginxの設定が正しいので、数行見逃しているだけです。
NginxでEventSource
を機能させる「魔法のトリオ」を次に示します。
proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;
それらをlocation
セクションに配置すると、動作するはずです。
追加する必要がある場合もあります
proxy_buffering off;
proxy_cache off;
それは公式の方法ではありません。
私は「試行錯誤」+「グーグル」でこれで終わった:)
別のオプションは、応答に値「no」の「X-Accel-Buffering」ヘッダーを含めることです。 Nginxはそれを特別に扱います。 http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering を参照してください。
これを自分で最初から書いてはいけません。 Nginxは素晴らしいイベントサーバーであり、アップストリームサーバーのパフォーマンスを低下させることなくSSEを処理するモジュールを備えています。
チェックアウト https://github.com/wandenberg/nginx-Push-stream-module
動作方法は、サブスクライバー(SSEを使用するブラウザー)がNginxに接続し、接続がそこで停止することです。パブリッシャー(Nginxの背後にあるサーバー)は、対応するルートでPOSTをNginxに送信し、その瞬間にNginxはブラウザーの待機中のEventSourceリスナーに転送します。
この方法は、Ruby webserverがこれらの「長いポーリング」を処理するよりもはるかにスケーラブルですSSE接続。