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