ruby - Eventos EventSource/Server-Enviado a través de Nginx
sinatra (3)
En el lado del servidor usando Sinatra con un bloque de stream
.
get ''/stream'', :provides => ''text/event-stream'' do
stream :keep_open do |out|
connections << out
out.callback { connections.delete(out) }
end
end
En el lado del cliente:
var es = new EventSource(''/stream'');
es.onmessage = function(e) { $(''#chat'').append(e.data + "/n") };
Cuando uso la aplicación directamente, a través de http://localhost:9292/
, todo funciona perfecto. La conexión es persistente y todos los mensajes se pasan a todos los clientes.
Sin embargo, cuando pasa por Nginx, http://chat.dev
, la conexión se interrumpe y la reconexión se dispara cada segundo más o menos.
La configuración de Nginx me parece bien:
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;
}
}
Intentó keepalive 1024
en la sección upstream
así como proxy_set_header Connection keep-alive;
en el location
Nada ayuda :(
No se transmiten conexiones ni mensajes persistentes a ningún cliente.
No escribas esto desde cero tú mismo. Nginx es un maravilloso servidor con evented y tiene módulos que manejarán SSE por usted sin ninguna degradación del rendimiento de su servidor en sentido ascendente.
Consulte https://github.com/wandenberg/nginx-push-stream-module
La forma en que funciona es que el suscriptor (navegador que usa SSE) se conecta a Nginx, y la conexión se detiene allí. El editor (su servidor detrás de Nginx) enviará un POST a Nginx en la ruta correspondiente y en ese momento Nginx lo reenviará inmediatamente al oyente de EventSource en espera en el navegador.
Este método es mucho más escalable que tener su servidor web Ruby manejando estas conexiones SSE de "larga votación".
Otra opción es incluir en su respuesta un encabezado ''X-Accel-Buffering'' con el valor ''no''. Nginx lo trata especialmente, vea http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering
Tu configuración de Nginx es correcta, solo faltas algunas líneas.
Aquí hay un "trío mágico" que hace que EventSource
trabaje a través de Nginx:
proxy_set_header Connection '''';
proxy_http_version 1.1;
chunked_transfer_encoding off;
Colóquelos en location
sección de location
y debería funcionar.
Es posible que también necesites agregar
proxy_buffering off;
proxy_cache off;
Esa no es una forma oficial de hacerlo.
Terminé con esto por "prueba y errores" + "googlear" :)