一、遇到的一些问题
记得 2008 年做性能测试的时候,新进7台 lenovo 4核4G 服务器用于性能测试。
当时资源紧张,这7台服务器都装了双系统(Win2003/CentOS5)空闲时用于做测试机(压测的Agent)。
当时给Nginx做了一系列测试,印象很深的是:在这批机器上,Nginx状态页面的压测。
短连接的话最佳QPS约4万,长连接的话最高QPS约13万。
大概3年后,那批 lenovo 服务器已经没人瞧得上了,只能做肉鸡。
然而,一次不经意的测试,发现再牛的服务器,短连接最佳QPS也高不了多少。而且,测试机的资源没用完,被测试服务器的资源也用不完,网络也没瓶颈。
服务器资源使用率很低,然而响应就是不够快。
最后,我们发现了瓶颈在监听的入口!是否可以提高监听入口的性能?是否可以端口复用?最后我们找到了SO_REUSEPORT。
SO_REUSEPORT支持多个进程或者线程绑定到同一端口,提高服务器程序的性能。
二、解决方案
测试环境
1
2
3
|
Dell PowerEdge M620 Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz
Linux 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt11-1+deb8u3 (2015-08-04) x86_64 GNU/Linux
Ethernet controller: Broadcom Corporation NetXtreme II BCM57810 10 Gigabit Ethernet (rev 10)
|
查看编译参数
tengine 配置如下:
注意有一个reuse_port参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
user www-data;
worker_processes auto;
events {
use epoll;
multi_accept on;
reuse_port on;
worker_connections 1048576;
}
dso { # 动态加载功能模块 /usr/share/nginx/modules
load ngx_http_memcached_module.so;
load ngx_http_limit_conn_module.so;
load ngx_http_empty_gif_module.so;
load ngx_http_scgi_module.so;
load ngx_http_upstream_session_sticky_module.so;
load ngx_http_user_agent_module.so;
load ngx_http_referer_module.so;
load ngx_http_upstream_least_conn_module.so;
load ngx_http_uwsgi_module.so;
load ngx_http_reqstat_module.so;
load ngx_http_browser_module.so;
load ngx_http_limit_req_module.so;
load ngx_http_split_clients_module.so;
load ngx_http_upstream_ip_hash_module.so;
}
http {
include /etc/nginx/mime.types;
default_type text/plain;
access_log off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
keepalive_timeout 120;
server_names_hash_bucket_size 512;
server_name_in_redirect off;
fastcgi_connect_timeout 3s;
fastcgi_send_timeout 3s;
fastcgi_read_timeout 3s;
fastcgi_buffer_size 128k;
fastcgi_buffers 8 128k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
variables_hash_max_size 1024;
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.28.0.0/16;
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Forwarded-For;
gzip off;
gzip_disable "msie6";
gzip_min_length 1k;
gzip_buffers 16 64k;
gzip_http_version 1.1;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_vary on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
server {
listen 80 backlog=65535;
charset utf-8;
location / { # 打印Tengine状态页
stub_status on; # 开启状态页,依赖 http_stub_status_module 模块
access_log off; #访问过程不记日志
}
deny all;
access_log off;
log_not_found off;
}
location ~ /\. { # 屏蔽.开头的目录或文件,比如 .htaccess .bash_history
deny all;
access_log off;
log_not_found off;
}
location /do_not_delete.html {
access_log off;
empty_gif;
}
}
}
|
nginx要如下配置开启:
http {
server {
listen 80 reuseport;
server_name localhost;
# ...
}
}
stream {
server {
listen 12345 reuseport;
# ...
}
}
压测 reuse_port
Tengine 早已支持 reuse_port 。开启 reuse_port 后,你会发现有很多进程同时监听80端口:
加压后你会发现,服务器性能可被你榨干:
对比一下测试 reuse_port 的效果,小伙伴们惊呆了(短连接QPS过了24万)!
真相大白后,你还等什么?
探个究竟
测试过程中由于压大 TCP: Possible SYN flooding on port 80. ,出大量错误 。
于是将并发量降到了6万 net.core.somaxconn = 65535 。
再关闭 reuse_port 后,我们看下 perf top的情况:
然后再打开 reuse_port ,对比 perf top 的情况:
此时再放大 Nginx 监听的 back_log ,看下资源使用情况:
我们来看看些时的队列情况(有入队过万了):
然后我们再来挑战30万并发(MTT是平均响应时间(ms)):
经过一系列调优,相同环境相同并发量,没有再出现 TCP: Possible SYN flooding on port 80.。但出现了少量连接超时的情况:
至此测试完毕,开启reuse_port确实可以让性能提升3倍,何不试试。