Devo me preocupar em pendurar soquetes ao definir o tempo limite de keep-alive para o Infinity?

2

Algum contexto inicial para esta questão. Atualmente eu tenho um cluster de aplicativo implantado por trás de um ALB que mantém persistentes manter conexões com o aplicativo. Esta aplicação está sob carga pesada contínua e deve ter um tempo de atividade muito alto. O ALB está enviando de volta 502 códigos de status Bad Gateway deste serviço. Indo mais a fundo e depois de capturar o pcap e capturar sysdig nas instâncias afetadas, vemos o seguinte (ordenado por sequência de eventos):

19:51:26.881806  10.23.34.195    10.23.67.39 HTTP    1068    POST /api HTTP/1.1  (application/json)
19:51:26.881838  10.23.67.39 10.23.34.195    TCP 66  80→52026 [ACK] Seq=7201 Ack=19033 Win=67072 Len=0 TSval=240987 TSecr=1566420
19:51:27.018305861 0 node (2989) > writev fd=120(<4t>10.23.34.195:52026->172.17.0.2:3000) size=400
19:51:27.018326  10.23.67.39 10.23.34.195    HTTP    466 HTTP/1.1 200 OK  (application/json)
19:51:27.018341806 0 node (2989) < writev res=400 data=HTTP/1.1 200 OK..Content-Type: application/json; charset=
19:51:27.018601  10.23.34.195    10.23.67.39 TCP 66  52026→80 [ACK] Seq=19033 Ack=7601 Win=47360 Len=0 TSval=1566454 TSecr=241021
19:51:32.042525  10.23.34.195    10.23.67.39 HTTP    1066    POST /api HTTP/1.1  (application/json)
19:51:32.042538  10.23.67.39 10.23.34.195    TCP 66  80→52026 [ACK] Seq=7601 Ack=20033 Win=69120 Len=0 TSval=242277 TSecr=1567710
19:51:32.066469320 0 node (2989) > close fd=120(<4t>10.23.34.195:52026->172.17.0.2:3000)
19:51:32.066470002 0 node (2989) < close res=0
19:51:32.066487  10.23.67.39 10.23.34.195    TCP 66  80→52026 [RST, ACK] Seq=7601 Ack=20033 Win=69120 Len=0 TSval=242283 TSecr=1567710

Como afirmado acima, parece que nosso aplicativo nodejs atinge 5 segundos de inatividade em uma conexão keep-alive (período de tempo limite keep alive), recebe uma solicitação de rede, fecha o soquete e finalmente responde à solicitação de rede enfileirada com um RST.

Portanto, parece que os 502s são devidos a uma condição de corrida em que uma nova solicitação é recebida do balanceador de carga entre ou durante a desmontagem TCP.

A solução mais aparente para esse problema seria garantir que o balanceador de carga seja a fonte da verdade ao derrubar essas conexões, garantindo que o tempo limite ocioso dos balanceadores de carga seja menor que o tempo limite no servidor de aplicativos. Esta solução funciona com os balanceadores de carga clássicos da AWS, mas não com o ALB, de acordo com seus documentos:

You can set an idle timeout value for both Application Load Balancers and Classic Load Balancers. The default value is 60 seconds. With an Application Load Balancer, the idle timeout value applies only to front-end connections.

http://docs.aws.amazon.com/elasticloadbalancing/latest/userguide/how-elastic-load-balancing-works.html

Alguém poderia especular por que a AWS pode ter removido o tempo limite ocioso de back-end (suponho que seja infinito)? Eu poderia definir o tempo limite de keep alive no servidor do nó para o Infinity também, mas devo me preocupar com o vazamento de soquetes? Existem outras tecnologias de servidor que lidam com esse problema mais facilmente que eu poderia aplicar para corrigir esse problema (sem usar balanceadores de carga clássicos)?

Além disso, o suporte da AWS declara que não respeitará um cabeçalho Keep-Alive enviado de volta do serviço.

    
por andrsnn 19.12.2017 / 07:32

2 respostas

1

Não podemos saber o motivo pelo qual eles não o têm. Não podemos conhecer as decisões de projeto / implementação da AWS que causam o comportamento. Somente pessoas que trabalham com a Amazon nesse recurso sabem, e provavelmente estão sob NDA.

Sua única chance de obter uma resposta válida para isso é perguntar à AWS.

    
por 19.12.2017 / 08:10
1

Não parece razoável acreditar que o ALB mantém conexões de back-end abertas indefinidamente, mas que o tempo limite configurável só se aplica a conexões front-end.

Estou um pouco preocupado com a quantidade de tempo decorrido entre a chegada e o ACK da solicitação em: 32.042 e o fechamento do fd em: 32.066. Você está planejando uma conexão que, na verdade, não está ociosa - ela aceitou uma solicitação 24ms antes. (!?) Para mim, é um tempo surpreendentemente "longo".

Conforme observado na mesma página nos documentos,

Classic Load Balancers use pre-open connections but Application Load Balancers do not.

Você não precisa se preocupar com vazamento de descritores, pois o ALB não abrirá conexões que ele realmente não precisa para solicitações de serviço ... mas você também não precisará de um tempo limite infinito.

A questão parece ser por quanto tempo o ALB mantém conexões de back-end ociosas abertas - o que parece ser não documentado, mas vou revisar meus logs e ver se consigo encontrar evidências para sugerir o que o timer pode ser definido, supondo que seja estático. (É claro que manter conexões de back-end abertas é uma otimização de desempenho.)

A intuição sugere que você pode tentar um temporizador de 75 segundos ao seu lado. Esses são os padrões estabelecidos com base no comportamento clássico do balanceador e não observei nenhum problema com ALBs colocados em seu lugar.

    
por 19.12.2017 / 13:33