Socket.io: AWS EC2 detrás de ELB siempre imprime un error Código de respuesta inesperado: 400

Creado en 30 oct. 2014  ·  66Comentarios  ·  Fuente: socketio/socket.io

Hola chicos -

Parece que no puedo encontrar una solución para esto, pero cuando ejecuto mi aplicación detrás de un balanceador de carga, aparece este error en el cliente:

WebSocket connection to 'wss://fakedomain.com/socket.io/?EIO=3&transport=websocket&sid=QH8VmXbiEcp3ZyiLAAAD' failed: Error during WebSocket handshake: Unexpected response code: 400 

Entiendo el error, ya que está tratando de comunicarse con el balanceador de carga y ahora con la instancia EC2 (no soy muy bueno con AWS, ¡así que no dude en ofrecer ayuda con esto!) pero lo que no entiendo es cómo hacer que el no aparece el error!

Me encantaría solucionar la causa raíz, pero supongo que involucra un servidor socket.io dedicado separado para manejar todas las cosas en tiempo real para las que no tengo tiempo en este momento, pero ¿podría alguien ayudarme a suprimir? ¿este error?

Supongo que está recurriendo al sondeo, que parece funcionar bien (tengo la conexión del zócalo conectada y se dispara), pero no quiero iniciar con un error rojo en mi consola.

¡Gracias de antemano por cualquier consejo que pueda tener!

Comentario más útil

Supongo que no está usando Elastic Beanstalk (las instrucciones allí serían mucho más fáciles).

Vaya a EC2->Red y seguridad->Balanceadores de carga

Seleccione su balanceador de carga y vaya a Oyentes. Asegúrese de que tanto el protocolo Load Balancer como el Instance Protocol estén configurados en TCP para el puerto 80 y SSL para el puerto 443 en lugar de HTTP y HTTPS.

Todos 66 comentarios

Además, he instalado a través de Bower si importa:

"socket.io-cliente": "~1.1.0",

¿Tienes una conexión pegajosa en tu servidor?

Supongo que no está usando Elastic Beanstalk (las instrucciones allí serían mucho más fáciles).

Vaya a EC2->Red y seguridad->Balanceadores de carga

Seleccione su balanceador de carga y vaya a Oyentes. Asegúrese de que tanto el protocolo Load Balancer como el Instance Protocol estén configurados en TCP para el puerto 80 y SSL para el puerto 443 en lugar de HTTP y HTTPS.

Oh hombre. Este es un consejo sólido que no he visto en ningún otro lugar. intentaré en la mañana
e informar de nuevo. ¡Gracias!

El miércoles 29 de octubre de 2014 a las 19:48 Vadim Kazakov [email protected]
escribió:

Supongo que no está usando Elastic Beanstalk (las instrucciones allí serían
ser mucho más fácil).

Vaya a EC2->Red y seguridad->Balanceadores de carga

Seleccione su balanceador de carga y vaya a Oyentes. Asegúrese de que tanto la Carga
El protocolo Balancer y el Protocolo de instancia se establecen en TCP para el puerto 80 y
SSL para el puerto 443 en lugar de HTTP y HTTPS.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/Automattic/socket.io/issues/1846#issuecomment-61038664
.

Entonces, tal vez me equivoque, pero nuestro sitio se ejecuta en HTTPS (con nuestro certificado SSL). Cambiarlos para romper muchas cosas en el futuro. Estaba revisando X-Forwarded-Proto en mi aplicación para asegurarme de que la solicitud fuera HTTPS y, de no ser así, obligarla a redirigir. Aparentemente, no hay un encabezado X-Forwarded-Proto con SSL/TCP y Express informa que req.secure es falso (aunque escribí https).

¿Sugerencia?

No estoy seguro, los sockets usan el protocolo TCP/SSL, no HTTP, por lo que deberá cambiarlo a TCP/SSL para que los sockets web funcionen. En cuanto a cómo arreglar el resto de tu aplicación, no tengo ni idea.

Gracias por la ayuda. Tendré que hacer un nuevo entorno y trastear un poco. ¡Hay muchos engranajes en la máquina!

¿Es posible ejecutar websockets en sus propios puertos? Si es así, ¿podría vincular alguna documentación? (Estoy bastante seguro de que no, pero podría estar equivocado)

Pueden funcionar en cualquier puerto que desee, solo especifique cuándo conecta el puerto de la siguiente manera:

io('https://myserver:123');

Estoy usando Elasticbeanstalk y me enfrento al mismo problema, no tengo SSL instalado pero estoy conectado a través de http normal.

Hola,
Tengo el mismo problema, aunque estoy usando SockJS.
mi aplicación es una aplicación Java Spring 4, funciona en una máquina de desarrollo y
obteniendo el mismo error en AWS.
parece que alguien está dejando caer el encabezado de actualización, puedo verlo en el cliente.

podría encontrar una solución todavía ...

Estoy en el mismo barco y en un chat en vivo con un ingeniero de AWS y ambos estamos perplejos. Confirmé que el ELB debe cambiarse de HTTP/HTTPS a TCP (o SSL (TCP seguro)), pero sigo recibiendo errores 400 frecuentes. Nunca tuve este problema hasta que me mudé al clúster con equilibrio de carga de Elastic Beanstalk.

intente comentar cualquier elemento de middleware de app.use (encabezado / cors relacionado) si corresponde, o app.get ("/", no estoy seguro de cuál funcionó para mí, pero publique sus resultados, por favor).

Actualización: he confirmado que es el ELB, ya sea que esté configurado para tráfico HTTP o HTTPS, socket.io falla. Cuando voy directamente a uno de los EC2, todo funciona muy bien.

Adjunto está lo que estoy viendo al pasar por el ELB.
snipimage

Parece que resolví mi problema agregando la instancia de Route53 frente al balanceador de carga.
Ahora tengo un websocket en funcionamiento con conexiones seguras en el entorno de AWS.

Intente agregar la Ruta 53, si esto no resuelve su problema, estaré encantado de compartir mi configuración.

@ yoav200 cree que podría compartir su configuración completa para saber qué hizo que las cosas funcionaran para usted. Es decir, puertos en seguridad EBS + protocolo (http/tcp), cualquier extensión .eb que necesite, etc. Probé un montón de cosas diferentes para piratear mis configuraciones nginx para mantener los encabezados de actualización y enviarlos al nodo, pero nada funcionó para mí . FWIW: una página wiki sería realmente útil para esto. Lo único que funcionó fue ir directamente a mi instancia de EC2.

Configuré una instancia de Route 53 que administra mi dominio.
Configuré una zona alojada con un registro que apunta mi dominio directamente al balanceador de carga.

el balanceador de carga está configurado para reenviar la solicitud a mis instancias de Tomcat, como se muestra aquí:
lb-listeners

el grupo de seguridad para ELB es bastante estándar:
lb-security-group

¿Estás usando nginx? ¿Tuviste que hacer algo especial en cuanto a la configuración?

Estoy muy cerca de que esto funcione, pasé casi 8 horas con un ingeniero de soporte de AWS durante los últimos dos días. Tuve que eliminar nginx de la mezcla, pero estoy muy cerca, los sockets funcionan bien a través de ELB sobre http, mañana creo que puedo manejar las cosas https del lado del servidor en lugar de a nivel de ELB.

Voy a informar de nuevo con mis hallazgos.

No uso nginx, gestiono todo en Amazon, también he movido mi dominio a Amazon,
sin embargo, migré mi aplicación desde un entorno de nube alojado que usa AWS para sus instancias, pero administré la carga con nginx y no tuve ningún problema allí.

cuando se les preguntó cómo funciona para ellos, su respuesta fue:

no usamos Amazon Elastic Load Balancer, usamos nuestra propia capa de equilibrio de carga NGinx.
Una solución podría ser usar un servidor Nginx o HAProxy en lugar del ELB y usar un grupo de escalado automático con 1 nodo de haproxy/nginx para garantizar la alta disponibilidad del componente.

Sí, me dijeron que HAProxy era otra opción, pero estoy bastante seguro de que lo tendré funcionando con los siguientes servicios al final del día:

  • Tallo de habichuelas elástico
  • ELB
  • Grupo EC2 Autoscaling (creado por EB)
  • RDS
  • ElastiCache

La aplicación de nodo está funcionando con todos estos servicios actualmente, pero como dije, solo a través de HTTP, por lo que no queda mucho por hacer para preparar la producción. Informaré con mis hallazgos/configuraciones más tarde.

@niczak , ¿podría compartir un poco de cómo funciona esto?

En este momento, intento conectarme a Socket.IO en mi instancia de Node en un EC2 junto con Redis de ElastiCache.

Abrí la instancia EC2 al público y respondí con una dirección IP pública para poder conectarme fácilmente al socket (http://coding-ceo.ghost.io/how-to-run-socket-io-behind -elb-on-aws/). en mi ELB estoy usando sesiones pegajosas (con la esperanza de que esto permanezca conectado), sin embargo, mi enchufe aún no se conecta y me da el encantador error: la conexión se cerró antes de recibir una respuesta de apretón de manos.

Sin embargo, el sondeo funciona bien, pero intenta que los sockets y la ruta completa funcionen bien.

Me encantaría ver un caso de uso aquí para poder configurar correctamente mi instancia (incluso si es solo en HTTP en lugar de http y https), ya que me he estado destrozando la cabeza durante bastante tiempo.

¡Muchas gracias por tu ayuda!

@petrogad

¡Hola Pete!

Mis oyentes ELB son tan simples como pueden ser (ver imagen) y, de forma predeterminada, en EC2, el puerto 80 se reenvía a 8080 mediante iptables. Dicho esto, puedo acceder a mi servidor en HTTPS, luego mi aplicación de nodo escucha en 8080 y entrega el certificado SSL en sí.

elb

El código de nodo para el manejo de certificados es el siguiente:

        files = ["COMODOHigh-AssuranceSecureServerCA.crt", "AddTrustExternalCARoot.crt"];
        ca = (function() {
            var _i, _len, _results;
            _results = [];
            for (_i = 0, _len = files.length; _i < _len; _i++) {
                file = files[_i];
                _results.push(fs.readFileSync('/etc/ssl/tcerts/' + file));
            }
            return _results;
            })();

        httpsOptions = {
            ca: ca,
            key: fs.readFileSync('/etc/ssl/tcerts/multidomain.key', 'utf8'),
            cert: fs.readFileSync('/etc/ssl/tcerts/14432575.crt', 'utf8')
        };

        this.serverPort = 8080;
        var httpsServer = https.createServer(httpsOptions, apiInstance);
        httpsServer.listen(this.serverPort);
        startSockets(httpsServer);

Para que los sockets web funcionen (sin recurrir a un sondeo largo), _tuve_ que deshabilitar el Equilibrio de carga entre zonas. Desafortunadamente, AWS no afirma admitir sockets web a través de su ELB, por lo que este tipo de "trucos" de configuración son necesarios. ¡Esperemos que esto sea suficiente para ponerte en marcha!

¡Gracias @niczak !

Todo funciona a la perfección, tenía tráfico HTTP que estaba echando a perder las cosas. También obtuve redis en múltiples instancias trabajando; lo último es simplemente trabajar en reCluster y permitir que una ruta tcp se quede con un trabajador en particular.

¿Has tenido mucho éxito con esto? Estoy usando express, por lo que sticky-session no ha funcionado muy bien. ¿Has tenido suerte con eso?

Gracias de nuevo y, con suerte, una vez que todo esté completo, se puede publicar una buena publicación en el blog para otras personas que luchan con un artículo similar.

Gracias @niczak !!

Finalmente conseguí que el mío también funcionara. Sin embargo, además de configurar
1) Balanceador de carga para usar el protocolo TCP
2) Equilibrador de carga para deshabilitar el equilibrio de carga entre zonas

tambien necesito configurar
3) El servidor proxy debe ser "ninguno" en la sección Configuración del software.

screen shot 2015-01-09 at 10 28 56 am

Esas son excelentes noticias @aidanbon y @petrogad , ¡hurra por los sockets en AWS! : +1:

¡Muchas gracias! Resolvió mi problema con las habichuelas mágicas elásticas. Tiene sentido eliminar el proxy nginx

Una actualización de mi publicación original:

Cambié mi HTTPS a SSL (443 ---> mi puerto personalizado) y dejé HTTP (80 ---> mi puerto personalizado).

Tengo un código que estaba comprobando con express !req.secure && X-Forwarded-Proto !=== https que te redirige a HTTPS si entras en el puerto 80...

SIN EMBARGO

Cambiar a SSL hace que X-Forwarded-Proto vuelva indefinido... rompiendo esta conexión. (También parece que req.secure puede estar en desuso)

Y ahora:

if (req.get('X-Forwarded-Proto') === 'http') {
            res.redirect('https://' + req.get('Host') + req.url);
        }

parece funcionar muy bien, y ya no aparece el error 400 en la consola.

Hola: conseguí que esto funcionara usando Node, NGINX, SSL y un ELB en Elastic Beanstalk haciendo lo siguiente:

Cree un comando de contenedor en .ebextensions para modificar el script de configuración de nginx para incluir websockets de proxy:

container_commands:
    00proxy:
        command: sed -i 's/proxy_http_version.*/proxy_http_version\ 1.1\;\n\ \ \ \ \ \ \ \ proxy_set_header\ \ \ \ \ \ \ \ Upgrade\ \ \ \ \ \ \ \ \ \$http_upgrade\;\n\ \ \ \ \ \ \ \ proxy_set_header\ \ \ \ \ \ \ \ Connection\ \ \ \ \ \ \"upgrade\"\;/g' /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf

Instale su certificado SSL en el balanceador de carga mediante la consola web de Elastic Beanstalk.

Luego vaya a la consola web de EC2 y cambie el balanceador de carga para escuchar en SSL 443 -> TCP 80. Esto no funcionó cuando lo cambié en la consola web de EB, tuve que hacerlo directamente en EC2.

Eso debería hacer que todo funcione. No he tenido que hacer ningún redireccionamiento y también logré que NGINX funcionara.

@ChrisEdson, ¿hay algo más que incluir en el paquete para usar esta solución?
Lo intenté pero la implementación falló debido a errores. El registro muestra la siguiente línea:

/etc/init.conf: Unable to load configuration: No such file or directory

¿Puedes publicar tu código?

El viernes 4 de septiembre de 2015 a la 1:13 p. m., Treyone [email protected] escribió:

@ChrisEdson, ¿hay algo más que incluir en el paquete para usar esta solución?
Lo intenté pero la implementación falló debido a errores. El registro muestra la siguiente línea:

/etc/init.conf: Unable to load configuration: No such file or directory

Responda a este correo electrónico directamente o véalo en GitHub:
https://github.com/socketio/socket.io/issues/1846#issuecomment-137718880

El código de la aplicación es una implementación de socket.io extremadamente básica, casi un ejemplo de uso listo para usar.
Lo único que agregué es el archivo .config en .ebextensions, en el que copié el fragmento de código que citó anteriormente.
Así que no tengo mucho que publicar :)

No se preocupe, es difícil depurar sin el código o los registros. ¿Puedes publicar los registros? Probablemente no sea apropiado quedarse aquí, tal vez ponerlos en un contenedor de pasta.

El viernes 4 de septiembre de 2015 a las 3:26 p. m., Treyone [email protected] escribió:

El código de la aplicación es una implementación de socket.io extremadamente básica, casi un ejemplo de uso listo para usar.
Lo único que agregué es el archivo .config en .ebextensions, en el que copié el fragmento de código que citó anteriormente.

Así que no tengo mucho que publicar :)

Responda a este correo electrónico directamente o véalo en GitHub:
https://github.com/socketio/socket.io/issues/1846#issuecomment-137749890

Hum, publiqué mi código a través de un gruñido en lugar de un paquete manual y funciona de maravilla. La automatización debería ser obligatoria ;)

¡Alegra oírlo!

El martes 8 de septiembre de 2015 a las 3:14 p. m., Treyone [email protected] escribió:

Hum, publiqué mi código a través de un gruñido en lugar de un paquete manual y funciona de maravilla. La automatización debería ser obligatoria ;)

Responda a este correo electrónico directamente o véalo en GitHub:
https://github.com/socketio/socket.io/issues/1846#issuecomment-138572724

¡Salva mi día!

También vimos este problema básico. Básicamente, debido a que SocketIO envía dos solicitudes para establecer la conexión websocket, si esas llamadas se federan entre instancias, la identificación de la sesión no se reconoce y el protocolo de enlace falla, lo que lleva a que SocketIO recurra a un sondeo prolongado. Esto es cierto ya sea que esté usando ws o wss o no; se supone que ha configurado el equilibrio de carga en la capa 4 (TCP), ya que no pude obtener el equilibrio de carga de la capa 7 (HTTP) para trabajar con websockets.

La solución sería habilitar sesiones pegajosas, de modo que una vez que una llamada pasa a una instancia, el balanceador de carga continúa enviando esas solicitudes a la misma instancia; sin embargo, si usa ELB de AWS, no le permiten usar sesiones persistentes para el equilibrio de carga de capa 4.

Lo que terminamos haciendo fue usar websockets sin procesar, en lugar de SocketIO, ya que entonces no hay datos de sesión que deban persistir entre llamadas (solo se realiza una llamada, el apretón de manos, y funciona).

Una solución por parte de AWS sería permitir que las sesiones pegajosas se usen de alguna manera para el equilibrio de carga de capa 4.

Una solución por parte de SocketIO sería hacer que el protocolo de enlace websocket no requiera el contexto de la ID de sesión anterior (no sé el propósito o el ciclo de vida en torno a esto; asumo que existe tanto para ayudar en el sondeo prolongado como para más volver a conectarse rápidamente en caso de que se termine la conexión; si el cliente determina que una conexión ha muerto, podría generar una nueva sesión y volver a conectarse con éxito, en lugar de que el backend rechace el protocolo de enlace porque creía que ya existía una conexión).

Una posible solución sería usar Redis para conservar el estado de la sesión en todas las instancias. No he probado esto.

Una solución alternativa, si su carga lo permite, es garantizar también una sola instancia de nodo por zona de disponibilidad y deshabilitar el equilibrio de carga entre zonas. De esa forma, todas las llamadas se establecerán de forma predeterminada en un solo nodo, lo que evitará este problema.

@aidanbon No pude encontrar Proxy server to be "none" in the Software Configuration section ?

Simplemente estoy usando un servidor ubuntu y MeteorJS con implementación de mup... ¿podría darme un enlace?

Salud

@sahanDissanayake Encontré la opción de configuración de mi servidor proxy a través de:

  1. Haga clic en "Configuración" en el entorno de interés
  2. Haga clic en "Configuración de software" desde la página de configuración
  3. El menú desplegable "Servidor proxy" como se muestra en mi captura de pantalla anterior.

Nota: mi entorno se aprovisionó hace casi un año. No estoy seguro de que el panel de AWS se haya actualizado para entornos más nuevos. Sin embargo, todavía puedo ver este menú desplegable hoy en mi entorno.

@aidanbon No uso ningún otro servicio que no sea ec2... ¿así que su configuración no es relevante para mí? ¿O necesito comenzar a usar este servidor poxy?

Entonces, el problema que tengo es que los websockets de mi aplicación web funcionan en el puerto 8080, pero NO en el puerto 80.

este es el problema

@lostcolony Gracias por el resumen. He llegado a la misma conclusión. ¿Ha leído esta publicación de blog: https://medium.com/@Philmod/load -balancing-websockets-on-ec2-1da94584a5e9#.hd2ectz8t? Básicamente, está diciendo que uno podría pasar la capa 4 (TCP) a través de una instancia HAProxy, que luego quita el encabezado PROXY y enruta el tráfico a la instancia correcta utilizando sesiones pegajosas. Sin embargo, no me queda claro cómo los dos HAProxy configuran su lista de servidores "backend" y dónde se ejecuta y dónde se ejecuta el servidor socket.io real. ¿Puedes darle algún sentido?

EDITAR: Creo que hice clic ahora. Conoce la lista porque tiene un conjunto conocido de servidores y no le importa el escalado automático...

La lista de servidores se configuraría en cada cuadro HAproxy. no estoy seguro de cómo
para hacer que funcione con instancias ec2 de escalado automático, a menos que haya escrito algunos
infraestructura adicional para actualizar esa lista cuando llegó un nuevo servidor
en línea. Socket.io se ejecutan en el mismo servidor que su aplicación web, por lo que
las conexiones entran a través de Elb, están federadas en una instancia de HAproxy,
las instancias de HAproxy aseguran que las conexiones de IP siempre vayan al mismo
servidor web/aplicación, que es donde se configuró socket.io.
El 13 de enero de 2016 a las 2:50 a. m., "Felix Schlitter" [email protected] escribió:

@lostcolony https://github.com/lostcolony Gracias por el resumen. I
han llegado a la misma conclusión. ¿Has leído esta publicación de blog?
https://medium.com/@Philmod/load-balancing-websockets-on-ec2-1da94584a5e9#.hd2ectz8t ?
Esencialmente está diciendo que uno podría pasar la capa 4 (TCP) a través de un
Instancia HAProxy, que luego quita el encabezado PROXY y enruta el
tráfico a la instancia correcta mediante sesiones pegajosas. Sin embargo, no es
me parece evidente cómo los dos HAProxy obtienen su lista de servidores "backend"
configurado y dónde se ejecuta y dónde se ejecuta el servidor socket.io real.
¿Puedes darle algún sentido?

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/socketio/socket.io/issues/1846#issuecomment-171208211
.

@lostcolony OK, vi que había un proyecto interesante con respecto al escalado automático en Amazon, usando HAProxy, al menos útil como referencia: https://github.com/markcaudill/haproxy-autoscale. Lo que no entiendo es ¿por qué usar un ELB frente a HAProxy? Debe haber solo una instancia de HAProxy; de lo contrario, ¿cómo garantizaría que ELB envíe tráfico a la instancia de HAProxy correcta? A menos que ellos (las instancias de HAProxy) compartieran una tabla adhesiva común de alguna manera usando ElastiCache o Redis o algo por el estilo. ... Me doy cuenta de que nos estamos desviando del tema.

Si tiene los HAProxies configurados para enrutar conexiones basadas en IP,
podría garantizar que terminaría en la misma instancia. Es decir, si los HAProxies
todos tenían la misma regla que decía que ip ABCD se dirige a la instancia uno,
luego, independientemente de qué HAProxy golpeó el ELB, terminaría en el mismo
lugar. Eso es lo que está pasando en ese enlace que enviaste, están equilibrando
a través de la fuente, lo que significa que la instancia de HAProxy procesa la IP y la usa para
determinar a qué instancia va. Múltiples HAProxies, siempre que todos
conocer las mismas instancias, enviaría tráfico de una ubicación a
la misma instancia de back-end.

El miércoles 13 de enero de 2016 a las 13:19, Felix Schlitter [email protected]
escribió:

@lostcolony https://github.com/lostcolony OK, vi que había un
proyecto interesante en lo que respecta al escalado automático en Amazon, usando HAProxy -
al menos útil para referencia:
https://github.com/markcaudill/haproxy-autoscale. Lo que no entiendo es por qué
usar un ELB frente a HAProxy? Solo debe haber una instancia de HAProxy,
de lo contrario, ¿cómo garantizaría que el ELB envíe tráfico a la derecha?
¿Instancia HAProxy? A menos que ellos (las instancias de HAProxy) compartieran un
tabla pegajosa de alguna manera usando ElastiCache o Redis o algo a lo largo de esos
¿líneas? ... Me doy cuenta de que nos estamos desviando del tema.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/socketio/socket.io/issues/1846#issuecomment-171386260
.

@lostcolony Entiendo que el hash se deriva de manera determinista para una IP dada, sin embargo, debe haber un mapeo de "hash -> instancia". En su caso, está diciendo que hay una regla que dice "ABCD se dirige a la instancia uno", pero ¿no le gustaría que HAProxy determine a dónde redirigir, dada una lista de servidores disponibles? Después de todo, "ABCD" es solo la IP de un cliente y no se conoce por adelantado.

La regla para asignar el hash a una instancia es la misma en todos los HAProxy
instancias. Es decir, ABCD dará como resultado el mismo hash sin importar el
Instancia HAProxy que golpea, y ese hash se asignará al mismo servidor, no
importa la instancia de HAProxy en uso, siempre que cada HAProxy conozca
las mismas instancias (y posiblemente en el mismo orden/los mismos nombres). El
las direcciones IP reales no tienen que conocerse por adelantado, porque son irrelevantes.
Cualquier IP generará hash en el mismo servidor independientemente del HAProxy que pase
mediante.

Para un ejemplo completamente falso (HAProxy usa algo que no es tan
predecible, estoy seguro), imagina que tuviéramos tres servidores, que están configurados
en orden como server0, server1 y serve2 (los detalles reales no importan,
solo que hay un orden claro, implícito está bien). Cada HAProxy
instancia tiene los mismos servidores, en el mismo orden. También tienen el mismo
regla sobre cómo tratar con una dirección IP entrante. Para este ejemplo trillado,
es sumar las cuatro partes de la dirección como números enteros (fácilmente extensible a
admite IPv6, sume todo como hexadecimal en base 10) y divida por 3, tome el
recordatorio. Entonces IP 123.12.61.24 = (123+12+61+24) % 3 o 1. Entonces se enruta
al servidor1. Así que no importa en qué instancia de HAProxy entre, eso
la conexión se enviará al servidor1.

Ahora, si el servidor 1 se desconecta, el algoritmo cambia en todos los HAProxy
instancias, al ser sumar todas las partes, módulo 2.

Y esto generalmente funciona, a menos que obtenga un netsplit (o configure el
Instancias HAProxy para tener una lista de servidores diferente). Donde un HAProxy ve
3 instancias, y otro ve 2. Si eso sucede, no se puede garantizar
para llegar al mismo backend. Y, de hecho, eso puede resultar ser un problema. Pero
esa es la solución que se describe en el enlace.

El miércoles 13 de enero de 2016 a las 15:51, Felix Schlitter [email protected]
escribió:

@lostcolony https://github.com/lostcolony Entiendo que el hash es
derivado de forma determinista para una ip dada, sin embargo, debe haber un mapeo
de "hash -> instancia". En su caso, está diciendo que hay una regla que es
diciendo "ABCD se dirige a la instancia uno", pero ¿no le gustaría
HAProxy para determinar a dónde redirigir, dada una lista de disponibles
servidores? Después de todo, "ABCD" es solo la IP de un cliente y no se conoce
parte delantera.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/socketio/socket.io/issues/1846#issuecomment-171428465
.

Descubrí que en Elastic Beanstalk a pesar de que había configurado el balanceador de carga para usar TCP y SSL con la interfaz web, cuando verifiqué la configuración del balanceador de carga directamente, todavía estaba usando HTTPS para el oyente seguro. Por lo tanto, probablemente debería verificar en la sección EC2> Load Balancers que los puertos estén configurados como deberían:

screen shot 2016-03-08 at 16 08 34

Una vez que esté ordenado, agregue lo siguiente a .ebextensions y todo funciona bien para mí :)

container_commands:
  01_nginx_static:
    command: |
      sed -i '/\s*proxy_set_header\s*Connection/c \
              proxy_set_header Upgrade $http_upgrade;\
              proxy_set_header Connection "upgrade";\
          ' /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf

Sin embargo, esto solo funcionará al 100 % cuando solo tenga una instancia, porque la compatibilidad con sesiones persistentes no funciona a través de TCP.

@lostcolony , la publicación de @williamcoates hace un momento me recordó agradecerle por la explicación. No puedo creer que me olvidé de hacer eso. Su explicación fue tremendamente útil, así que gracias por tomarse el tiempo.

Así que tuve el mismo problema y resultó que había configurado el ECB para usar HTTPS.
Cambié HTTPS a SSL y ya no recibo el mensaje.
entonces, simplemente no use HTTP/HTTPS sino TCP/SSL

A partir de agosto de 2016, puede usar el Balanceador de carga de aplicaciones (ALB) de Amazon en lugar del ELB "clásico". Trabajó "fuera de la caja" para mí con oyentes en HTTP 80 y HTTPS 443.

@trans1t Buen hombre, ¡gracias por la información! Tendré que comprobar eso.

@niczak : también

@aidanbon Esa es una información fantástica, ¡muchas gracias por compartirla!

Para cualquiera que todavía tenga un problema con AWS Application Load Balancer, intente actualizar su política de seguridad. Me encontré con el mismo problema a pesar de que funcionaba perfectamente bien en la configuración exacta para otro sitio web, pero noté que la política de seguridad estaba atrasada aproximadamente 1 año. Actualizarlo a uno más nuevo parece haber resuelto el problema.

@michaelmitchell , ¿cambió algo o simplemente lo actualizó sin modificarlo?

No cambié nada en mi aplicación, el único paso adicional que tomé fue eliminar y volver a agregar el agente de escucha HTTPS en el ALB, ya que después de cambiar a la nueva política no pareció funcionar.

Sin embargo, aprendí que ver el error incluso después de actualizar la política de seguridad probablemente era mi sesión del navegador manteniendo la política de seguridad anterior, por lo que no estoy seguro de si realmente era necesario agregar/volver a agregar el oyente, pero abrir de incógnito funcionó bien y después cerrar todas mis sesiones de Chrome y volver a abrir funcionó bien y no lo he visto desde entonces.

¡Es bueno saberlo, gracias!

Le ven. 31 de marzo de 2017 a las 12:02, Michael Mitchell [email protected] a
escrito:

No cambié nada en mi solicitud, el único paso adicional que hice
tomar fue eliminar y volver a agregar el oyente HTTPS en el ALB como después
cambiar a la nueva política no pareció funcionar.

Sin embargo, aprendí que ver el error incluso después de actualizar la seguridad
la política era probablemente la sesión de mi navegador que se aferraba a la antigua política de seguridad
así que no estoy seguro de si era realmente necesario agregar/volver a agregar el oyente, pero
abrir de incógnito funcionó bien y después de cerrar todas mis sesiones de Chrome
y reabrirlo funcionó bien y no lo he visto desde entonces.

-
Estás recibiendo esto porque comentaste.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/socketio/socket.io/issues/1846#issuecomment-290672158 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/ADrIi_SXqccWOLUMIWF1IhClGXvKAGMcks5rrM8sgaJpZM4C0swP
.

Parece que este hilo se convirtió en un lugar para resolver problemas con AWS/socket.io—

Mi configuración es que el cliente realiza una solicitud HTTPS con datos para una conexión socket.io.
La solicitud HTTPS debe responder con las cookies necesarias para las sesiones permanentes. El problema es que no puedo pasar un encabezado cookie en la conexión socket.io.

Estoy usando un ALB con estos oyentes:
image

Lo que apunta a un grupo objetivo con adherencia configurada así:
image

Primero llegué al punto final HTTPS con:

fetch(`https://${url}/hub/api/spinup/${uuid}`, {
                method: 'GET',
                headers: headers,
            })

luego inicialice el socket con

connection = io(`wss://${url}:443/`, {
            path: `/user/${uuid}/spawn`,
        })

La instancia a la que llega la solicitud HTTPS _debe_ ser la instancia a la que llega la conexión del socket.

Una vez que se establece un socket (si llega a la instancia correcta por pura suerte), permanece allí y las cosas funcionan bien, el problema es lograr que el websocket llegue al mismo punto final que la solicitud HTTPS.

Mi primer instinto es usar

connection = io(`wss://${url}:443/`, {
    path: `/user/${uuid}/spawn`,
    extraHeaders: {
        cookie: cookieValueFromFetchResponse
    }
})

Esto funciona en node , pero en el navegador cookie es un encabezado prohibido en XMLHTTPRequests, por lo que no puedo enviarlo.

¿Alguien ha hecho algo similar?

No he hecho algo similar, pero, aunque los ALB aún no tienen enrutamiento basado en encabezado, sí tienen enrutamiento basado en host. Esto es extremadamente pirateado, como tal, pero básicamente podría hacerlo de modo que cada instancia detrás del ALB tenga una ruta explícita hacia él, que la instancia conozca. Cuando sale esa solicitud HTTP inicial, parte de la respuesta incluye la ruta y la conexión para el websocket incluye esa ruta. Es decir, la solicitud HTTP llega a la instancia '5' (según cualquier criterio; los UUID generados serían mejores), devuelve '5' como parte de la respuesta y el websocket se abre en url/5. El ALB tiene una regla de que url/5 se enruta a la instancia 5.

Si está utilizando el ajuste de escala automático (y sus instancias son ganado, no mascotas), necesitará que su código se ejecute en la instancia y modifique la configuración de ALB para enrutar el dominio apropiado hacia ella.

Lea más aquí: https://aws.amazon.com/blogs/aws/new-host-based-routing-support-for-aws-application-load-balancers/

Sin embargo, también diré que probablemente desee evitar el patrón que está utilizando si es posible. Los datos que provienen de la solicitud HTTP deben almacenarse de manera que sean accesibles para todas las instancias (base de datos o similar), o deben enviarse a través de la conexión websocket una vez que se haya establecido. Tal como está, aún podría tener una instancia que muere entre la solicitud HTTP y la apertura del websocket, y podría encontrarse con el mismo problema (aunque con mucha menos frecuencia)

@lostcolony gracias por el consejo, definitivamente vale la pena intentarlo.

la solicitud http es lo que activa el servidor websocket (en realidad está en un contenedor docker, pero eso se abstrae). las dos solicitudes deben enrutarse a la misma instancia para que el servidor websocket exista en la instancia a la que se está conectando

con esta línea, ayuda a colocar el servidor jupyter detrás del elb.

service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp

en caso de que alguien venga a este ticket con kubernetes en aws.

Acabo de desactivar el HTTP2 entonces está bien para mí. No tiene que hacer nada más con respecto a ELB.

Screen Shot 2019-12-13 at 16 12 49

Hola,
Tengo el mismo problema, aunque estoy usando SockJS.
mi aplicación es una aplicación Java Spring 4, funciona en una máquina de desarrollo y
obteniendo el mismo error en AWS.
parece que alguien está dejando caer el encabezado de actualización, puedo verlo en el cliente.

podría encontrar una solución todavía ...

Hola @yoav200 ,

SÁLVAME.
Estoy atrapado en el mismo problema. Por favor ayuda
Estoy usando Springboot 2.x y SockJs para websocket
Creé la aplicación tomcat implementada en aws,
Beanstalk elástico con balanceador de carga clásico

Ahora el problema es
El desarrollador de iOS no puede conectarse, llega a mi backend pero falla durante el protocolo de enlace
a continuación se muestran los registros que obtengo tanto en CLB como en ALB


2019-12-13 15:21:22.662 DEPURACIÓN 27543 --- [nio-8080-exec-2] oswsDispatcherServlet: OBTENER "/wtchat/websocket", parámetros = {}
2019-12-13 15:21:22.701 DEPURACIÓN 27543 --- [nio-8080-exec-2] oswsssWebSocketHandlerMapping: asignado a org.springframework.web.socket.sockjs.support. SockJsHttpRequestHandler@30c6a17
2019-12-13 15:21:22.714 DEBUG 27543 --- [nio-8080-exec-2] oswssthDefaultSockJsService: Solicitud de procesamiento de transporte: GET http://mydomain.com/wtchat/websocket
2019-12-13 15: 21: 22.716 ERROR 27543 --- [nio-8080-exec-2] cwcMyHandshakeHandler: Handshake falló debido a un encabezado de actualización no válido: nulo

2019-12-13 15:21:22.717 DEPURACIÓN 27543 --- [nio-8080-exec-2] oswsDispatcherServlet: Completado 400 BAD_REQUEST

he seguido lo que has dicho
image
image

creó un conjunto de registros en Route 53 que apunta directamente al equilibrador de carga.

Después de hacer esto, también obtengo el mismo error que el anterior.

¿Qué más necesito hacer?

¿Fue útil esta página
0 / 5 - 0 calificaciones