nginx 1.7.9:反向代理Web套接字:挂起服务停止/服务重新启动,从不退出

我们使用nginx对一对websocket服务器进行负载均衡,并遇到了问题。

一旦将stream量实际连接到Web套接字服务器,它将不会优雅地退出或closures。 比如service nginx stop,或者nginx -s quit或者nginx -s reload会导致一个或者多个工作进程永远报告“worker process is shutting down”。

stream程是:

  1. 用下面的configuration启动nginx。
  2. 将stream量传递给nginx端点(即使使用networking浏览器打到443端口并获得404错误就足够了)
  3. 使用服务控制或发送退出命令
  4. nginx现在挂起来了。

我们在centos v6上运行nginx

我们的编译选项和高级configuration的细节:

[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/ 

我们的configuration如下。 我们怎么去追逐这个呢? 现在我们不得不努力杀死/重新启动nginx来更新configuration。

 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; } } } 

可能netstattcpdump对于debugging以及lsof是有用的 – 工作进程仍然连接和交换数据? 我注意到你的proxy_read_timeout是一天,而不是默认的60年代,不知道这是否意义重大。 这听起来像一个nginx错误,可能这个关于ZLIB压缩和keepalive的post是相关的: http : //forum.nginx.org/read.php?2,170139,209671

我会做的是使用strace附加到nginx进程,然后尝试closures它,并检查你的strace ,看看它挂在哪个文件描述符。 有了这个信息,使用lsof来追踪它正在等待的文件描述符并从那里开始。 我的猜测是它可能是你的上游服务器之一造成这一点。

如果它是一个像浏览器websocket协议的websocket服务器,它需要将websocketclosures发送到连接的浏览器并closures套接字。 在192.168.2。*:3842的应用程序将能够这样做。 所以你需要发送一个信号给该应用程序,告诉它发送关机到其连接的websocket。