[原创] Nginx1.13版本reload过程对TCP包影响的测试
Nginx1.13版本reload过程中各项连接情况和状态的测试。测试Nginx1.13 Reload过程中,对客户端和服务器的TCP层面的包影响。
1)对客户端开启长连接,服务端开启/不开启长连接情况下
测试方法:浏览器发起http自带connection:keep-alive,服务端分别在开启和不开启长连接的情况下,然后在重新打开浏览器访问,连续访问5次,期间会reload nginx。整个过程对81和8010端口抓包。
2)对TCP长连接代理的情况下
测试方法:连接82端口,发送tcp,再发送tcp1,断开连接。然后连接ws,发送tcp_reload,执行nginx reload,再发送tcp_reload1,断开连接。整个过程抓82和8012端口的包。
3)对Websocket保持连接的情况下
测试方法:连接ws,发送hello,再发送hello1,断开连接。然后连接ws,发送hello_reload,执行nginx reload,再发送hello_reload1,断开连接。整个过程抓81和8010端口的包。
如下所示,是测试的环境访问流程。三项测试都是用该环境。
** 测试代码见文章末尾
1)对客户端开启长连接,服务端开启/不开启长连接情况下
1.1)环境的配置:
Real server使用python的SimpleHTTPServer模块启动一个简单的web服务,监听8010端口。如下图所示:
1.2)Nginx的配置:
不开启长连接时的配置如下,开启长连接时把注释去掉即可:
upstream websocket { server localhost:8010; #keepalive 2; } server { listen 81; server_name localhost; location /websocket { proxy_pass http://websocket/; #proxy_http_version 1.1; #proxy_set_header Connection ""; }
1.3)测试方法:浏览器发起http自带connection:keep-alive,服务端分别在开启和不开启长连接的情况下,然后在重新打开浏览器访问,连续访问5次,期间会reload nginx。整个过程对81和8010端口抓包。
81端口的抓包情况如下:
开启长连接时8010端口的抓包情况如下:
发现开启了长连接之后每次请求都会新建连接,进行三次握手,这是因为SimpleHTTPServer没有做处理的原因,换成tomcat(8080端口)之后,同样配置下访问五次使用的是同一个连接进行传输的。如下所示:
不开启长连接时8010端口的抓包情况如下:
2)对TCP长连接代理的情况下
2.1)环境的配置:
Real server使用python实现TCP Server,监听8012端口。如下图所示:
客户端使用python实现TCP Client。连接nginx的82端口。如下图所示:
2.2)Nginx的配置:
tcp代理的配置如下:
stream { upstream tcp_server { server localhost:8012 weight=5; } server { listen 82; proxy_responses 1; proxy_timeout 20s; proxy_pass tcp_server; } }
2.3)测试方法:连接82端口,发送tcp,再发送tcp1,断开连接。然后连接ws,发送tcp_reload,执行nginx reload,再发送tcp_reload1,断开连接。整个过程抓82和8012端口的包。
82端口抓到的包如下:
8012端口抓到的包如下:
2.4)nginx reload前后进程状态对比:
3)对Websocket保持连接的情况下
3.1)环境的配置:
Real server使用nodejs的启动一个简单的websocket服务,监听8010端口。如下图所示:
客户端连接如下:
3.2)Nginx的配置:
不开启长连接时的配置如下,开启长连接时把map段和proxy_set_header注释即可:
upstream websocket { server localhost:8010; #keepalive 2; } server { listen 81; server_name localhost; location /websocket { proxy_pass http://websocket/; #proxy_http_version 1.1; #proxy_set_header Connection ""; }
3.3)测试方法:连接ws,发送hello,再发送hello1,断开连接。然后连接ws,发送hello_reload,执行nginx reload,再发送hello_reload1,断开连接。整个过程抓81和8010端口的包。
81端口抓到的包如下:
8010端口抓到的包如下:
3.4)nginx reload前后进程状态对比:
结论:综上分析可知,不管nginx是否开启长连接,nginx在reload过程中,nginx对客户端和反向代理的后端在TCP代理,websocket代理和upstream反向代理的情况下均没有影响,nginx会在reload时把正常处理连接的worker设置shutting down状态,不接受新的请求,然后新启动一个worker进程接收处理新的请求,shutting down的worker直至处理完当前连接之后优雅退出。对于客户端的连接也是一样的。
# cat tcp_server.py # -*- coding: utf-8 -*- import SocketServer from SocketServer import StreamRequestHandler as SRH from time import ctime import time import sys reload(sys) sys.setdefaultencoding('utf8') #host = '127.0.0.1' host='127.0.0.1' port = 8012 addr = (host, port) class Servers(SRH): def handle(self): print 'got connection from ', self.client_address self.wfile.write('connection %s:%s at %s succeed!' % (host, port, ctime())) while True: data = self.request.recv(1024) if not data: break #print data cur_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) print "%s RECV from %s, data is:%s" % (cur_time,self.client_address[0],data) self.request.send(data) print 'server is running....' server = SocketServer.ThreadingTCPServer(addr, Servers) server.serve_forever()
# cat server.js console.log("Server started"); var Msg = ''; var WebSocketServer = require('ws').Server , wss = new WebSocketServer({port: 8010}); wss.on('connection', function(ws) { ws.on('message', function(message) { console.log('Received from client: %s', message); ws.send('Server received from client: ' + message); }); });