phpwebsockets node ruby-on-rails nginx reverse-proxy websocket thin

ruby-on-rails - node - phpwebsockets



¿Se puede usar nginx como un proxy inverso para un servidor websocket de back-end? (7)

¿Qué hay de Nginx con el nuevo módulo HTTP Push: http://pushmodule.slact.net/ . Se encarga de los malabares de conexión (por así decirlo) que uno podría tener que preocuparse con un proxy inverso. Sin duda, es una alternativa viable a Websockets que aún no están completamente mezclados. Sé que el desarrollador del módulo HTTP Push todavía está trabajando en una versión completamente estable, pero está en desarrollo activo. Hay versiones de él siendo utilizado en bases de código de producción. Para citar al autor, "Una herramienta útil con un nombre aburrido".

Estamos trabajando en una aplicación Ruby on Rails que necesita aprovechar websockets html5. Por el momento, tenemos dos "servidores" separados, por así decirlo: nuestra aplicación principal se ejecuta en nginx + pasajero, y un servidor separado que utiliza el framework Cramp Pratik Naik (que se ejecuta en Thin ) para manejar las conexiones websocket.

Idealmente, cuando llegara el momento de la implementación, tendríamos la aplicación de rieles ejecutándose en nginx + pasajero, y el servidor de websocket sería proxy detrás de nginx, por lo que no necesitaríamos que el servidor websocket se ejecute en un puerto diferente.

El problema es que, en esta configuración, parece que nginx está cerrando las conexiones a Thin demasiado pronto. La conexión se establece exitosamente en el servidor Thin, luego se cierra inmediatamente con un código de respuesta de 200. Nuestra suposición es que nginx no se da cuenta de que el cliente está tratando de establecer una conexión de larga duración para el tráfico de websocket.

Es cierto que no soy tan listo con la configuración nginx, entonces, ¿es posible configurar nginx para que funcione como un proxy inverso para un servidor websocket? ¿O debo esperar a que nginx brinde soporte para el nuevo handshake de websocket? Suponiendo que tener el servidor de aplicaciones y el servidor de websocket escuchando en el puerto 80 es un requisito, ¿podría significar que tengo que ejecutar Thin en un servidor por separado sin nginx en el frente por el momento?

Gracias de antemano por cualquier consejo o sugerencia. :)

-John


¿Qué le parece usar mi módulo nginx_tcp_proxy_module ?

Este módulo está diseñado para proxy TCP general con Nginx. Creo que también es adecuado para websocket. Y solo agregué tcp_ssl_module en la rama de desarrollo.


Fuera de la caja (es decir, fuentes oficiales), Nginx solo puede establecer conexiones HTTP 1.0 en sentido ascendente (= backend), lo que significa que no hay posibilidad de mantenimiento: Nginx seleccionará un servidor en sentido ascendente, conexión abierta, proxy, caché (si lo desea ) y cierra la conexión. Eso es.

Esta es la razón fundamental por la que los marcos que requieren conexiones persistentes con el servidor no funcionarían a través de Nginx (sin HTTP / 1.1 = sin keepalive y sin websockets, supongo). A pesar de tener esta desventaja, hay un beneficio evidente: Nginx puede elegir entre varias fuentes ascendentes (equilibrio de carga) y failover a una activa en caso de que algunas de ellas fallen.

Editar : Nginx admite HTTP 1.1 para backends y keepalive desde la versión 1.1.4. "fastcgi" y "proxy" upstreams son compatibles. Aquí están los documentos


Para cualquiera que se pregunte sobre el mismo problema, nginx ahora oficialmente admite HTTP 1.1 en sentido ascendente. Consulte la documentación de nginx para "keepalive" y "proxy_http_version 1.1".


Uso nginx para invertir el proxy en un servidor estilo cometa con largas conexiones de sondeo y funciona muy bien. Asegúrese de configurar proxy_send_timeout y proxy_read_timeout a los valores apropiados. También asegúrese de que su servidor de back-end que nginx está aprobando admite http 1.0 porque no creo que el módulo proxy de nginx tenga aún http 1.1.

Solo para despejar la confusión en algunas de las respuestas: Keepalive permite a un cliente reutilizar una conexión para enviar otra solicitud HTTP. No tiene nada que ver con el sondeo prolongado o la celebración de conexiones abiertas hasta que se produce un evento que es lo que preguntaba la pregunta original. Por lo tanto, no importa que el módulo proxy de nginx solo sea compatible con HTTP 1.0 que no tiene keepalive.


nginx (> = 1.3.13) ahora admite websockets de proxy inverso.

# the upstream server doesn''t need a prefix! # no need for wss:// or http:// because nginx will upgrade to http1.1 in the config below upstream app_server { server localhost:3000; } server { # ... location / { proxy_pass http://app_server; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; } }


No puede usar nginx para esto actualmente [ya no es cierto] , pero le sugiero que busque HAProxy. Lo he usado exactamente para este propósito.

El truco es establecer largos tiempos de espera para que las conexiones de socket no estén cerradas. Algo como:

timeout client 86400000 # In the frontend timeout server 86400000 # In the backend

Si desea servir, por ejemplo, una aplicación de rieles y calambres en el mismo puerto, puede usar las reglas de ACL para detectar una conexión de websocket y usar un backend diferente. Por lo tanto, su configuración de frontend haproxy se vería como

frontend all 0.0.0.0:80 timeout client 86400000 default_backend rails_backend acl websocket hdr(Upgrade) -i WebSocket use_backend cramp_backend if websocket

Para completar, el backend se vería como

backend cramp_backend timeout server 86400000 server cramp1 localhost:8090 maxconn 200 check