Socket.io: AWS EC2 atrás do ELB sempre imprime erro Código de resposta inesperado: 400

Criado em 30 out. 2014  ·  66Comentários  ·  Fonte: socketio/socket.io

Ei pessoal -

Não consigo encontrar uma solução para isso, mas quando executo meu aplicativo atrás de um balanceador de carga, recebo este erro no cliente:

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

Eu entendo o erro, pois está tentando falar com o balanceador de carga e agora com a instância do EC2 (não sou muito bom com a AWS, então sinta-se à vontade para oferecer ajuda neste!), mas o que não entendo é como fazer o erro não aparece!

Eu adoraria corrigir a causa raiz, mas acho que envolve um servidor socket.io dedicado separado para lidar com todas as coisas em tempo real para as quais não tenho tempo no momento, mas alguém poderia me ajudar a suprimir esse erro?

Estou assumindo que está voltando ao polling, o que parece funcionar bem (tenho a conexão do soquete conectada e ela é acionada), mas não quero iniciar com um erro vermelho no meu console.

Agradecemos antecipadamente por qualquer conselho que você possa ter!

Comentários muito úteis

Suponho que você não esteja usando o Elastic Beanstalk (as instruções seriam muito mais fáceis).

Vá para EC2->Rede e Segurança->Load Balancers

Selecione seu balanceador de carga e vá para Ouvintes. Certifique-se de que o protocolo Load Balancer e o Instance Protocol estejam configurados como TCP para a porta 80 e SSL para a porta 443 em vez de HTTP e HTTPS.

Todos 66 comentários

Além disso, instalei via bower se for importante:

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

Você tem conexão pegajosa no seu servidor?

Suponho que você não esteja usando o Elastic Beanstalk (as instruções seriam muito mais fáceis).

Vá para EC2->Rede e Segurança->Load Balancers

Selecione seu balanceador de carga e vá para Ouvintes. Certifique-se de que o protocolo Load Balancer e o Instance Protocol estejam configurados como TCP para a porta 80 e SSL para a porta 443 em vez de HTTP e HTTPS.

Oh cara. Este é um conselho sólido que eu não vi em nenhum outro lugar. vou tentar amanha
e reporte de volta. Obrigada!

Na quarta-feira, 29 de outubro de 2014, 19h48 Vadim Kazakov [email protected]
escreveu:

Suponho que você não esteja usando o Elastic Beanstalk (as instruções
ser muito mais fácil).

Vá para EC2->Rede e Segurança->Load Balancers

Selecione seu balanceador de carga e vá para Ouvintes. Certifique-se de que tanto a carga
O protocolo Balancer e o Instance Protocol são definidos como TCP para a porta 80 e
SSL para a porta 443 em vez de HTTP e HTTPS.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/Automattic/socket.io/issues/1846#issuecomment -61038664
.

Então talvez eu esteja enganado, mas nosso site está rodando em HTTPS (com nosso certificado SSL). Mudá-los para quebra um monte de coisas no futuro. Eu estava verificando o X-Forwarded-Proto no meu aplicativo para garantir que a solicitação fosse HTTPS e, se não, forçando-a a redirecionar. Aparentemente, não há cabeçalho X-Forwarded-Proto com SSL/TCP e o Express está relatando req.secure como falso (mesmo que eu digitei https).

Sugestão?

Não tenho certeza, os soquetes usam o protocolo TCP/SSL e não o HTTP, então você precisará alterá-lo para TCP/SSL para fazer os soquetes da Web funcionarem. Quanto a como corrigir o resto do seu aplicativo, não tenho ideia.

Obrigado pela ajuda. Vou ter que fazer um novo ambiente e mexer um pouco. Há muitas engrenagens na máquina!

É possível ter websockets rodando em suas próprias portas? Em caso afirmativo, você poderia vincular alguma documentação? (tenho certeza que não, mas posso estar errado)

Eles podem funcionar em qualquer porta que você quiser, basta especificar quando você conectar a porta assim:

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

Estou usando o Elasticbeanstalk e enfrentando o mesmo problema, não tenho SSL instalado, mas conectado através de http regular.

Oi,
Eu tenho o mesmo problema, embora eu esteja usando o SockJS.
meu aplicativo é um aplicativo Java Spring 4, funciona na máquina de desenvolvimento e
obtendo o mesmo erro na AWS.
parece que o cabeçalho Upgrade está sendo descartado por alguém, posso vê-lo no cliente.

poderia encontrar uma solução ainda...

Estou no mesmo barco e em um bate-papo ao vivo com um engenheiro da AWS e nós dois estamos perplexos. Confirmei que o ELB precisa ser alterado de HTTP/HTTPS para TCP (ou SSL (Secure TCP)), mas ainda recebo erros 400 frequentes. Nunca tive esse problema até migrar para o cluster com balanceamento de carga do Elastic Beanstalk.

por favor, tente comentar qualquer coisa de middleware app.use (cabeçalho/cors relacionados) se houver, ou app.get("/", não tenho certeza qual funcionou para mim, mas poste seus resultados por favor.

Atualização: confirmei que é o ELB, esteja configurado para tráfego HTTP ou HTTPS, o socket.io falha. Quando vou diretamente a um dos EC2s tudo funciona muito bem.

Em anexo está o que estou vendo ao passar pelo ELB.
snipimage

Parece que resolvi meu problema adicionando a instância Route53 na frente do loadbalancer.
agora tenho um websocket funcionando com conexões seguras no ambiente AWS.

Tente adicionar o Route 53, se isso não estiver resolvendo seu problema, ficarei feliz em compartilhar minha configuração.

@yoav200 acha que poderia compartilhar toda a sua configuração para o que fez as coisas funcionarem para você? Ou seja, portas na segurança do EBS + protocolo (http/tcp), quaisquer .ebextensions que você precisava, etc. Eu tentei várias coisas diferentes para hackear minhas configurações do nginx para manter os cabeçalhos de atualização e enviá-los para o nó, mas nada funcionou para mim . FWIW - uma página wiki seria muito, muito útil para isso. A única coisa que funcionou foi ir direto para minha instância do EC2.

Configurei uma instância do Route 53 que gerencia meu domínio.
configurei uma Zona Hospedada com um registro que aponta meu domínio diretamente para o balanceador de carga.

o balanceador de carga está configurado para encaminhar a solicitação para minhas instâncias do Tomcat, conforme mostrado aqui:
lb-listeners

o grupo de segurança para ELB é bastante padrão:
lb-security-group

Você está usando o nginx? Você teve que fazer algo especial em termos de configuração?

Estou muito perto de fazer isso funcionar, passei quase 8 horas com um engenheiro de suporte da AWS nos últimos dois dias. Tive que extrair o nginx da mistura, mas estou muito perto, os soquetes estão funcionando bem através do ELB sobre http, amanhã acho que posso lidar com o lado do servidor https em vez de no nível do ELB.

Retornarei com minhas descobertas.

Não uso nginx, gerencio tudo na Amazon, mudei meu domínio para a Amazon também,
no entanto, migrei meu aplicativo de um ambiente de nuvem hospedado que usa AWS para suas instâncias, mas gerenciei a carga com nginx e não tive nenhum problema lá.

quando perguntados como está funcionando para eles, sua resposta foi:

não usamos o Amazon Elastic Load Balancer, usamos nossa própria camada de balanceamento de carga NGinx.
Uma solução pode ser usar um servidor Nginx ou HAProxy em vez do ELB e usar um grupo de dimensionamento automático com 1 nó do haproxy/nginx para garantir a alta disponibilidade do componente.

Sim, me disseram que o HAProxy era outra opção, mas tenho certeza de que ele funcionará com os seguintes serviços até o final do dia:

  • Pé de Feijão Elástico
  • ELB
  • Grupo de escalonamento automático do EC2 (criado pelo EB)
  • RDS
  • ElastiCache

O aplicativo do nó está trabalhando com todos esses serviços atualmente, mas como eu disse, apenas por HTTP, então não há muito o que fazer para preparar a produção. Voltarei com minhas descobertas/configurações mais tarde.

@niczak você poderia compartilhar um pouco de como isso funciona?

No momento, estou tentando me conectar ao Socket.IO na minha instância do Node em um EC2 junto com o Redis do ElastiCache.

Abri a instância do EC2 para o público e respondi com um endereço IP público para que eu pudesse me conectar facilmente ao soquete (http://coding-ceo.ghost.io/how-to-run-socket-io-behind -elb-on-aws/). no meu ELB estou usando sticky sessions (esperando que isso permaneça conectado), no entanto, meu soquete ainda não se conecta e me dá a adorável falha: Conexão fechada antes de receber uma resposta de handshake.

O polling funciona bem, mas tentando fazer com que os soquetes e todo o caminho funcionem bem.

Adoraria ver um caso de uso aqui para que eu possa configurar corretamente minha instância (mesmo que seja apenas em HTTP em vez de http e https), pois estou me quebrando há um bom tempo.

Muito obrigado pela sua ajuda!

@petrogad

Oi Pete!

Meus ouvintes ELB são tão simples quanto possível (veja a imagem) e por padrão na porta EC2 80 é encaminhado para 8080 usando iptables. Com isso dito, posso acessar meu servidor em HTTPS, então meu aplicativo de nó escuta em 8080 e fornece o próprio certificado SSL.

elb

O código do nó para manipulação de certificados é o seguinte:

        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 os soquetes da Web funcionem (sem voltar a uma sondagem longa), eu _desabilitei o balanceamento de carga entre zonas. Infelizmente, a AWS não afirma oferecer suporte a web sockets por meio de seu ELB, portanto, esses tipos de "hacks" de configuração são necessários. Espero que isso seja suficiente para colocá-lo em funcionamento!

Obrigado @niczak !

Tudo está funcionando perfeitamente, o tráfego HTTP estava acontecendo, o que estava atrapalhando. Também obtive redis em várias instâncias funcionando; a última coisa é apenas trabalhar no reCluster e permitir que uma rota tcp fique com um determinado trabalhador.

Você teve muito sucesso com isso? Estou usando o express, então a sessão adesiva não está funcionando muito bem. Você teve alguma sorte com isso?

Obrigado novamente e espero que, uma vez que tudo esteja concluído, possa obter uma boa postagem no blog para outras pessoas que lutam com um item semelhante.

Obrigado @niczak !!

Finalmente consegui que o meu também funcionasse. No entanto, além de configurar
1) Balanceador de carga para usar o protocolo TCP
2) Balanceador de carga para desabilitar o balanceamento de carga entre zonas

Eu também preciso definir
3) O servidor proxy deve ser "nenhum" na seção Configuração do software.

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

Isso é uma ótima notícia @aidanbon e @petrogad , huzzah para sockets na AWS! : +1:

Muito obrigado! Resolveu meu problema com o pé de feijão elástico. Faz sentido remover o proxy nginx

Uma atualização do meu post original:

Eu tenho meu HTTPS alterado para SSL (443 ---> minha porta personalizada) e deixei HTTP (80 ---> minha porta personalizada).

Eu tenho um código que estava verificando com express !req.secure && X-Forwarded-Proto !=== https que redireciona você para HTTPS se você entrar na porta 80 ...

CONTUDO

Mudar para SSL faz com que o X-Forwarded-Proto volte indefinido.... quebrando esta conexão. (também req.secure parece estar obsoleto)

Então agora:

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

parece funcionar muito bem e não recebo mais o erro 400 no console.

Hullo - Eu consegui isso usando Node, NGINX, SSL e um ELB no Elastic Beanstalk fazendo o seguinte:

Crie um comando de contêiner em .ebextensions para modificar o script de configuração do 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 seu certificado SSL no balanceador de carga usando o console da web do Elastic Beanstalk.

Em seguida, vá para o console da web do EC2 e altere o balanceador de carga para escutar no SSL 443 -> TCP 80. Isso não funcionou quando alterei no console da web do EB, tive que fazer isso diretamente no EC2.

Isso deve fazer tudo funcionar. Não precisei fazer nenhum redirecionamento e consegui fazer o NGINX funcionar também.

@ChrisEdson há mais alguma coisa para incluir no pacote para usar esta solução?
Eu tentei, mas a implantação falhou devido a erros. O log mostra a seguinte linha:

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

Você pode postar o código?

Em sex, 4 de setembro de 2015 às 13:13, Treyone [email protected] escreveu:

@ChrisEdson há mais alguma coisa para incluir no pacote para usar esta solução?
Eu tentei, mas a implantação falhou devido a erros. O log mostra a seguinte linha:

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

Responda a este e-mail diretamente ou visualize-o no GitHub:
https://github.com/socketio/socket.io/issues/1846#issuecomment -137718880

O código do aplicativo é uma implementação de socket.io extremamente básica, quase um exemplo de uso fora da caixa.
A única coisa que adicionei foi o arquivo .config em .ebextensions, no qual copiei o trecho de código que você citou anteriormente.
Então não tenho muito o que postar :)

Não se preocupe, é difícil depurar sem o código ou os logs. Pode postar os logs? Provavelmente não é apropriado ficar aqui, talvez colocá-los em uma lixeira.

Em sex, 4 de setembro de 2015 às 15:26, Treyone [email protected] escreveu:

O código do aplicativo é uma implementação de socket.io extremamente básica, quase um exemplo de uso fora da caixa.
A única coisa que adicionei foi o arquivo .config em .ebextensions, no qual copiei o trecho de código que você citou anteriormente.

Então não tenho muito o que postar :)

Responda a este e-mail diretamente ou visualize-o no GitHub:
https://github.com/socketio/socket.io/issues/1846#issuecomment -137749890

Hum, publiquei meu código via grunt em vez de uma embalagem manual e funciona como um encanto. A automatização deveria ser obrigatória ;)

Fico feliz em ouvi-lo!

Em terça - feira, 8 de setembro de 2015 às 15h14, Treyone

Hum, publiquei meu código via grunt em vez de uma embalagem manual e funciona como um encanto. A automatização deveria ser obrigatória ;)

Responda a este e-mail diretamente ou visualize-o no GitHub:
https://github.com/socketio/socket.io/issues/1846#issuecomment -138572724

Salve meu dia!

Também vimos esse problema básico. Basicamente, como o SocketIO envia duas solicitações para estabelecer a conexão websocket, se essas chamadas forem federadas entre instâncias, o ID da sessão não será reconhecido e o handshake falhará, levando o SocketIO a retornar a uma sondagem longa. Isso é verdade independentemente de você estar usando ws ou wss; ele pressupõe que você configurou o balanceamento de carga na camada 4 (TCP), pois não consegui fazer o balanceamento de carga da camada 7 (HTTP) funcionar com websockets.

A correção seria habilitar sessões fixas, de modo que, uma vez que uma chamada passe para uma instância, o balanceador de carga continue a enviar essas solicitações para a mesma instância; no entanto, se você estiver usando os ELBs da AWS, eles não permitirão o uso de sessões fixas para balanceamento de carga de camada 4.

O que acabamos fazendo foi usar websockets brutos, em vez de SocketIO, pois não há dados de sessão que precisem ser persistidos nas chamadas (apenas uma chamada, o handshake, ocorre e funciona).

Uma correção por parte da AWS seria permitir que sessões fixas fossem usadas de alguma maneira para balanceamento de carga de camada 4.

Uma correção por parte do SocketIO seria fazer com que o handshake do websocket não exija o contexto do sessionID anterior (não sei o propósito ou o ciclo de vida em torno disso; estou assumindo que existe tanto para ajudar a sondagem longa quanto para mais reconectar rapidamente no caso de encerramento da conexão; se o cliente determinar que uma conexão foi interrompida, ele poderá gerar uma nova sessão e reconectar com sucesso, em vez de o back-end recusar o handshake porque acreditava que já existia uma conexão).

Uma possível correção seria usar o Redis para persistir o estado da sessão em todas as instâncias. Eu não testei isso.

Uma solução alternativa, se sua carga permitir, também é garantir apenas uma única instância de nó por zona de disponibilidade e desabilitar o balanceamento de carga entre zonas. Dessa forma, todas as chamadas serão padronizadas para um único nó, evitando esse problema.

@aidanbon não consegui encontrar Proxy server to be "none" in the Software Configuration section ?

Estou simplesmente usando um servidor ubuntu e MeteorJS com implantação mup .. você poderia me dar um link?

Felicidades

@sahanDissanayake Encontrei minha opção de configuração do Proxy Server via:

  1. Clique em "Configuração" no Ambiente de interesse
  2. Clique em "Configuração de software" na página de configuração
  3. O menu suspenso "Servidor proxy", conforme mostrado na captura de tela anterior.

Observação: meu ambiente foi provisionado há quase um ano. Não tenho certeza se o painel da AWS foi atualizado para ambientes mais recentes. No entanto, ainda posso ver essa lista suspensa hoje no meu ambiente.

@aidanbon Eu não uso nenhum outro serviço além do ec2 .. então suas configurações não são relevantes para mim? ou eu preciso começar a usar este servidor poxy?

Portanto, o problema que tenho é que meus websockets de aplicativos da Web funcionam na porta 8080, mas NÃO na porta 80.

Esta é a questão

@lostcolony Obrigado pelo resumo. Cheguei à mesma conclusão. Você já leu esta postagem no blog: https://medium.com/@Philmod/load -balancing-websockets-on-ec2-1da94584a5e9#.hd2ectz8t? Ele está essencialmente dizendo que é possível passar a camada 4 (TCP) para uma instância HAProxy, que então retira o cabeçalho PROXY e roteia o tráfego para a instância correta usando sessões fixas. No entanto, não é aparente para mim como os dois HAProxy configuram sua lista de servidores "backend" e onde ela é executada e onde o servidor socket.io real é executado. Você pode fazer algum sentido disso?

EDIT: Acho que cliquei agora. Ele conhece a lista porque tem um conjunto conhecido de servidores e não se importa com o escalonamento automático...

A lista de servidores seria configurada em cada caixa HAproxy. não tenho certeza de como
para fazer isso funcionar com instâncias ec2 de escalonamento automático, a menos que você tenha escrito algumas
infraestrutura adicional para atualizar essa lista quando um novo servidor chegar
conectados. Socket.io eles estão sendo executados no mesmo servidor que seu aplicativo Web, então
as conexões chegam através do Elb, são federadas a uma instância HAproxy,
a(s) instância(s) do HAproxy garantem que as conexões de IPs sempre vão para o mesmo
servidor web/app, que é onde o socket.io foi configurado.
Em 13 de janeiro de 2016 02:50, "Felix Schlitter" [email protected] escreveu:

@lostcolony https://github.com/lostcolony Obrigado pelo resumo. eu
chegaram à mesma conclusão. Você já leu esta postagem no blog:
https://medium.com/@Philmod/load -balancing-websockets-on-ec2-1da94584a5e9#.hd2ectz8t?
Ele está essencialmente dizendo que se poderia passar a camada 4 (TCP) para um
instância HAProxy, que então retira o cabeçalho PROXY e roteia o
tráfego para a instância correta usando sessões fixas. No entanto, não é
aparente para mim como os dois HAProxy obtêm sua lista de servidores "backend"
configurado e onde ele é executado e onde o servidor socket.io real é executado.
Você pode fazer algum sentido disso?

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/socketio/socket.io/issues/1846#issuecomment -171208211
.

@lostcolony OK, vi que havia um projeto interessante em relação ao dimensionamento automático na amazon, usando HAProxy - pelo menos útil para referência: https://github.com/markcaudill/haproxy-autoscale. O que não entendo é por que usar um ELB na frente do HAProxy? Deve haver apenas uma instância HAProxy, caso contrário, como você garantiria que o ELB envie tráfego para a instância HAProxy correta? A menos que eles (as instâncias do HAProxy) compartilhassem uma tabela fixa comum de alguma forma usando ElastiCache ou Redis ou algo nesse sentido? ... Eu percebo que estamos indo _way_ fora do tópico.

Se você tiver os HAProxies configurados para rotear conexões com base no IP,
poderia garantir que acabaria na mesma instância. Ou seja, se os HAProxies
todos tinham a mesma regra dizendo que o ip ABCD é direcionado para a instância um,
então, independentemente de qual HAProxy o ELB atingiu, ele terminaria no mesmo
Lugar, colocar. Isso é o que está acontecendo nesse link que você enviou, eles estão equilibrando
via fonte, o que significa que a instância do HAProxy faz o hash do IP e o usa para
determinar para qual instância ele vai. Vários HAProxies, desde que todos
saber sobre as mesmas instâncias, enviaria tráfego de um local para outro
a mesma instância de back-end.

Na quarta-feira, 13 de janeiro de 2016 às 13h19, Felix Schlitter [email protected]
escreveu:

@lostcolony https://github.com/lostcolony OK, eu vi que havia um
projeto interessante em relação ao dimensionamento automático na amazon, usando HAProxy -
pelo menos útil para referência:
https://github.com/markcaudill/haproxy-autoscale. O que eu não entendo é por que
usar um ELB na frente do HAProxy? Deve haver apenas uma instância HAProxy,
caso contrário, como você garantiria que o ELB envie tráfego para a direita
instância HAProxy? A menos que eles (as instâncias HAProxy) compartilhassem um
tabela pegajosa de alguma forma usando ElastiCache ou Redis ou algo assim
linhas? ... Eu percebo que estamos indo _way_ fora do tópico.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/socketio/socket.io/issues/1846#issuecomment -171386260
.

@lostcolony Entendo que o hash é derivado de forma determinística para um determinado ip, no entanto, deve haver um mapeamento de "hash -> instância". No seu caso, você está dizendo que há uma regra que diz "ABCD é direcionado para a instância um", mas você não gostaria que o HAProxy determinasse para onde redirecionar, dada uma lista de servidores disponíveis? Afinal, "ABCD" é apenas o ip de algum cliente e não é conhecido de antemão.

A regra para mapear o hash para uma instância é a mesma em todos os HAProxy
instâncias. Ou seja, ABCD resultará no mesmo hash, independentemente do
instância HAProxy que atinge, e esse hash será mapeado para o mesmo servidor, não
importa a instância do HAProxy em uso, desde que cada HAProxy saiba
as mesmas instâncias (e possivelmente na mesma ordem/os mesmos nomes). O
IPs reais não precisam ser conhecidos de antemão, porque são imateriais.
Qualquer IP será hash para o mesmo servidor, independentemente do HAProxy que ele passar
Através dos.

Para um exemplo completamente falso (HAProxy usa algo que não é tão
previsível, tenho certeza), imagine que tivéssemos três servidores, que estão configurados
em ordem como server0, server1 e serve2 (os detalhes reais não importam,
apenas que há uma ordenação clara, implícita está bem). Cada HAProxy
instância tem os mesmos servidores, na mesma ordem. Eles também têm o mesmo
regra sobre como lidar com um endereço IP de entrada. Para este exemplo banal,
é somar todas as quatro partes do endereço como números inteiros (facilmente extensível a
suporta IPv6, some tudo como hexadecimal na base 10) e divida por 3, pegue o
restante. Então IP 123.12.61.24 = (123+12+61+24) % 3, ou 1. Então ele é roteado
para servidor1. Portanto, não importa em qual instância do HAProxy ele venha, isso
conexão será enviada para server1.

Agora, se server1 ficar offline, o algoritmo muda em todos os HAProxy
instâncias, para somar todas as partes, módulo 2.

E isso geralmente funciona -a menos que você obtenha um netsplit (ou configure o
instâncias HAProxy para ter uma lista de servidores diferente). Onde um HAProxy vê
3 instâncias e outra vê 2. Se isso acontecer, você não pode garantir
para alcançar o mesmo back-end. E, de fato, isso pode ser um problema. Mas
essa é a solução que está sendo descrita no link.

Na quarta-feira, 13 de janeiro de 2016 às 15h51, Felix Schlitter [email protected]
escreveu:

@lostcolony https://github.com/lostcolony Eu entendo que o hash é
derivado deterministicamente para um determinado ip, no entanto, deve haver um mapeamento
de "hash -> instância". No seu caso você está dizendo que existe uma regra que é
dizendo "ABCD é direcionado para a instância um", mas você não quer
HAProxy para determinar para onde redirecionar, dada uma lista de
servidores? Afinal, "ABCD" é apenas o ip de algum cliente e não é conhecido
frente.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/socketio/socket.io/issues/1846#issuecomment -171428465
.

Descobri que no Elastic Beanstalk, embora eu tivesse configurado o balanceador de carga para usar TCP e SSL com a interface da web, quando verifiquei a configuração do balanceador de carga diretamente, ele ainda estava usando HTTPS para o listener seguro. Portanto, você provavelmente deve verificar na seção EC2 > Load Balancers se as portas estão configuradas como deveriam:

screen shot 2016-03-08 at 16 08 34

Uma vez que é classificado, adicione o seguinte a .ebextensions e tudo funciona bem para mim :)

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

No entanto, isso só funcionará 100% quando você tiver apenas uma instância, porque o suporte a sessões fixas não funciona sobre TCP.

@lostcolony , @williamcoates post agora me lembrou de agradecer pela explicação. Não acredito que esqueci de fazer isso. Sua explicação foi extremamente útil, então obrigado por dedicar seu tempo.

Então, eu tive o mesmo problema e acabei configurando o ECB para usar HTTPS.
Mudei HTTPS para SSL e não recebo mais a mensagem.
então, apenas não use HTTP/HTTPS, mas TCP/SSL

A partir de agosto de 2016, você pode usar o Application Load Balancer (ALB) da Amazon em vez do ELB "clássico". Funcionou "fora da caixa" para mim com ouvintes em HTTP 80 e HTTPS 443.

@trans1t Doce cara, obrigado pela informação! Vou ter que verificar isso.

@niczak - Eu também mudei para ALB para aderência do tráfego de soquete. No entanto, primeiro lutei com a configuração do ALB Sticky Sessions (já que não havia muitos documentos sobre esse assunto; pelo menos alguns meses atrás). Finalmente descobri. O principal é que "A aderência é definida no nível do grupo-alvo", portanto, certifique-se de criar um grupo-alvo para atender ao seu tráfego e, em seguida, adicionar aderência a ele.

@aidanbon Que informação fantástica, muito obrigado por compartilhar!

Para quem ainda está tendo problemas com o AWS Application Load Balancer, tente atualizar sua política de segurança, encontrei o mesmo problema, embora estivesse funcionando perfeitamente bem na configuração exata de outro site, mas notei que a política de segurança estava cerca de 1 ano atrasada. Atualizá-lo para um mais recente parece ter resolvido o problema.

@michaelmitchell você mudou alguma coisa ou apenas atualizou sem modificação?

Não alterei nada no meu aplicativo, a única etapa adicional que fiz foi remover e adicionar novamente o ouvinte HTTPS no ALB, pois depois de alterar para a nova política não parecia funcionar.

Eu aprendi, no entanto, que ver o erro mesmo depois de atualizar a política de segurança provavelmente era a minha sessão do navegador segurando a política de segurança antiga, então não tenho certeza se adicionar/re-adicionar o ouvinte era realmente necessário, mas abrir incógnito funcionou bem e depois fechar todas as minhas sessões do Chrome e reabri-lo funcionou bem e não o vejo desde então.

Bom saber, obrigado!

Le ven. 31 de março de 2017 às 12:02, Michael Mitchell [email protected] a
escrito:

Não alterei nada na minha aplicação, o único passo adicional que fiz
tomar foi remover e adicionar novamente o listener HTTPS no ALB como depois
mudar para a nova política não pareceu funcionar.

Eu aprendi, no entanto, que ver o erro mesmo depois de atualizar a segurança
política era provavelmente minha sessão do navegador mantendo a antiga política de segurança
então não tenho certeza se adicionar/re-adicionar o ouvinte era realmente necessário, mas
abrindo incógnito funcionou bem e depois de fechar todas as minhas sessões do chrome
e reabri-lo funcionou bem e não o vi desde então.

-
Você está recebendo isto porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/socketio/socket.io/issues/1846#issuecomment-290672158 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/ADrIi_SXqccWOLUMIWF1IhClGXvKAGMcks5rrM8sgaJpZM4C0swP
.

Parece que este tópico se tornou um lugar para descobrir problemas com AWS/socket.io—

Minha configuração é que o cliente faça uma solicitação HTTPS com dados para uma conexão socket.io.
A solicitação HTTPS deve responder com os cookies necessários para sessões permanentes. O problema é que não consigo passar um cabeçalho cookie na conexão socket.io.

Estou usando um ALB com esses ouvintes:
image

O que aponta para um grupo-alvo com aderência configurada assim:
image

Eu atingi o endpoint HTTPS primeiro com:

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

em seguida, inicialize o soquete com

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

A instância que a solicitação HTTPS atinge _deve_ ser a instância que a conexão do soquete atinge.

Uma vez que um soquete é estabelecido (se atingir a instância correta por sorte), ele permanece lá e as coisas funcionam bem, o problema é fazer com que o websocket atinja o mesmo endpoint que a solicitação HTTPS.

Meu primeiro instinto é usar

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

Isso funciona em node , mas no navegador cookie é um cabeçalho proibido em XMLHTTPRequests, então não consigo enviá-lo.

Alguém já fez algo parecido?

Eu não fiz semelhante, mas, embora os ALBs ainda não tenham roteamento baseado em cabeçalho, eles têm roteamento baseado em host. Isso é extremamente hackish, como tal, mas você pode basicamente fazer com que cada instância por trás do ALB tenha um caminho explícito para ele, que a instância conheça. Quando essa solicitação HTTP inicial é enviada, parte da resposta inclui o caminho e a conexão para o websocket inclui esse caminho. Ou seja, a solicitação HTTP atinge a instância '5' (com base em qualquer critério; UUIDs gerados seriam melhores), retorna '5' como parte da resposta e o websocket é aberto para url/5. O ALB tem uma regra que url/5 é roteado para a instância 5.

Se você estiver usando o escalonamento automático (e suas instâncias forem gado, não animais de estimação), será necessário que seu código em execução na instância modifique as configurações do ALB para rotear o domínio apropriado para ela.

Leia mais aqui: https://aws.amazon.com/blogs/aws/new-host-based-routing-support-for-aws-application-load-balancers/

No entanto, também direi que você provavelmente deseja evitar o padrão que está usando, se possível. Os dados que chegam na solicitação HTTP devem ser armazenados de forma acessível a todas as instâncias (DB ou similar), ou devem ser enviados pela conexão websocket assim que ela for estabelecida. Como está, você ainda pode ter uma instância morta entre a solicitação HTTP e a abertura do websocket, e você pode encontrar o mesmo problema (embora com muito menos frequência)

@lostcolony obrigado pelo conselho - definitivamente vale a pena tentar.

a solicitação http é o que aciona o servidor websocket (na verdade, está em um contêiner docker, mas é abstraído). as duas solicitações precisam ser roteadas para a mesma instância para que o servidor websocket exista na instância que está sendo conectada

com esta linha, ajuda a colocar o servidor jupyter atrás do elb.

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

caso alguém venha a este ticket com kubernetes no aws.

Eu apenas desabilito o HTTP2 então está tudo bem para mim. Você não precisa fazer mais nada sobre o ELB.

Screen Shot 2019-12-13 at 16 12 49

Oi,
Eu tenho o mesmo problema, embora eu esteja usando o SockJS.
meu aplicativo é um aplicativo Java Spring 4, funciona na máquina de desenvolvimento e
obtendo o mesmo erro na AWS.
parece que o cabeçalho Upgrade está sendo descartado por alguém, posso vê-lo no cliente.

poderia encontrar uma solução ainda...

Olá @yoav200 ,

ME SALVE.
Estou preso no mesmo problema. Por favor ajude
Estou usando Springboot 2.xe SockJs para websocket
Eu criei o aplicativo tomcat implantado no aws,
Pé de feijão elástico com balanceador de carga clássico

Agora o problema é
O desenvolvedor do iOS não consegue se conectar, chega ao meu back-end, mas falha durante o handshake
abaixo estão os logs que recebo no CLB e no ALB


13/12/2019 15:21:22.662 DEBUG 27543 --- [nio-8080-exec-2] oswsDispatcherServlet : GET "/wtchat/websocket", parameters={}
13/12/2019 15:21:22.701 DEBUG 27543 --- [nio-8080-exec-2] oswsssWebSocketHandlerMapping : Mapeado para org.springframework.web.socket.sockjs.support. SockJsHttpRequestHandler@30c6a17
13/12/2019 15:21:22.714 DEBUG 27543 --- [nio-8080-exec-2] oswssthDefaultSockJsService: Processando solicitação de transporte: GET http://mydomain.com/wtchat/websocket
13/12/2019 15:21:22.716 ERRO 27543 --- [nio-8080-exec-2] cwcMyHandshakeHandler: Falha no handshake devido a cabeçalho de atualização inválido: null

13-12-2019 15:21:22.717 DEBUG 27543 --- [nio-8080-exec-2] oswsDispatcherServlet: Concluído 400 BAD_REQUEST

Eu segui o que você disse
image
image

criou um conjunto de registros no Route 53 que aponta diretamente para o balanceador de carga.

Depois de fazer isso também estou recebendo o mesmo erro acima.

O que mais eu preciso fazer?

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

LeonFedotov picture LeonFedotov  ·  36Comentários

jitendrapawar picture jitendrapawar  ·  46Comentários

darrachequesne picture darrachequesne  ·  51Comentários

sjones6 picture sjones6  ·  36Comentários

edmellum picture edmellum  ·  130Comentários