[原创] 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);
    });
 });

原文地址:https://www.cnblogs.com/wsjhk/p/11430613.html