Usamos nginx para balanceamento de carga para um par de servidores websocket e encontramos um problema.
Ele não sairá ou desligará normalmente depois de conectar o tráfego a um servidor de soquete da web. Por exemplo, service nginx stop ou nginx -s quit ou nginx -s reload faz com que um ou mais processos de trabalho relatem "o processo de trabalho está sendo encerrado" para sempre.
O fluxo é:
- Inicie o nginx com a configuração abaixo.
- Passe o tráfego para o endpoint nginx (mesmo usando o navegador da web para acessar a porta 443 e obter o erro 404 é suficiente)
- Use o controle de serviço ou envie o comando quit
- nginx agora está travado.
Nós rodamos nginx no centos v6
Detalhes de nossas opções de compilação e configuração de alto nível:
[root@nginx1 nginx]# nginx -V
nginx version: nginx/1.7.9
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC)
TLS SNI support enabled
configure arguments: --user=nginx --group=nginx --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --with-http_gzip_static_module
--with-http_ssl_module --add-module=/opt/nginx_upstream_check_module-master/
Nossa configuração está abaixo. Como vamos perseguir isso? No momento, somos forçados a executar/reiniciar o nginx para atualizar a configuração.
worker_processes 2;
error_log logs/error.log;
events {
worker_connections 20000;
}
worker_rlimit_nofile 40000;
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream websocketserver {
server 192.168.2.16:3842 max_fails=1 fail_timeout=60s;
server 192.168.2.19:3842 max_fails=1 fail_timeout=60s;
}
server {
listen 192.168.2.28:80;
location / {
proxy_pass http://websocketserver;
proxy_next_upstream error timeout invalid_header http_500;
proxy_connect_timeout 2;
proxy_read_timeout 86400;
# WebSocket support (nginx 1.4)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location / {
deny all;
return 404;
}
}
}
Possivelmente
netstat
etcpdump
são úteis para depuração, bem comolsof
- o processo de trabalho ainda está conectado e trocando dados? Percebo que o seuproxy_read_timeout
é um dia em vez do padrão 60 e me pergunto se isso é significativo. Parece um bug nginx, e possivelmente este post sobre compactação ZLIB e keepalive está relacionado: http://forum.nginx.org/read.php?2,170139,209671O que eu faria é anexar ao processo nginx usando
strace
, então tentar desligá-lo e verificar o seustrace
para ver em qual descritor de arquivo ele está pendurado. Com esta informação, uselsof
para rastrear qual descritor de arquivo está esperando e partir daí. Meu palpite é que pode ser um dos seus servidores upstream causando isso.Se for um servidor websocket como o protocolo websocket do navegador, ele precisa enviar o desligamento do websocket para os navegadores conectados e fechar o soquete. O aplicativo em 192.168.2.*:3842 seria capaz de fazer isso. Portanto, você precisaria enviar um sinal para esse aplicativo para dizer a ele para enviar o desligamento aos seus websockets conectados.