当管理大量连接时,特别是只有少量活跃连接,NGINX有比较好的CPU和RAM利用率,如今是多终端保持在线的时代,更能让NGINX发挥这个优点。本文做一个简单测试,NGINX在一个普通PC虚拟机上维护100k的HTTP长连接,然后查看NGINX和系统的资源利用率。
软件:CentOS 6.5, kernel 2.6.32, gcc 4.4.7, nginx 1.4.7
内核参数调整:
$ /sbin/sysctl -w net.netfilter.nf_conntrack_max=102400 # 提升系统整体连接数
$ /sbin/sysctl net.netfilter.nf_conntrack_max #验证是否生效
NGINX从源码编译时带--with-http_stub_status_module,只列出与默认设置不同的部分:
worker_rlimit_nofile 102400;
worker_connections 102400;
# 设一个比较大得超时,客户端能以平缓的方式发送HEAD请求来维持KeepAlive
软件:CentOS 6.5, kernel 2.6.32, gcc 4.4.7, Python 3.3.5
$ /sbin/sysctl -w net.ipv4.ip_local_port_range="1024 61024” #实际只使用50000个端口
$ /sbin/sysctl net.ipv4.ip_local_port_range #验证是否生效
$ vi /etc/security/limits.conf #提升当前用户的最大打开文件数nofile(hard >= soft > 50000)
$ ulimit -n #验证是否生效,可能需重启shell
$ pyvenv ~/pyvenv #创建虚拟环境,便于测试
$ . ~/pyvenv/bin/activate #激活虚拟环境
(pyvenv) $ python get-pip.py #从pip官网下载get-pip.py
(pyvenv) $ pip install asyncio #安装异步IO模块
因为Apache ab只能批量请求,不能维持连接,所以自己写了一个HTTP长连接测试工具asyncli.py,详细实现见 。
(pyvenv) $ python --help
usage: [-h] [-c CONNECTIONS] [-k KEEPALIVE] url
-h, --help show this help message and exit
-c CONNECTIONS, --connections CONNECTIONS
number of connections simultaneously
-k KEEPALIVE, --keepalive KEEPALIVE
每隔10毫秒连续创建10个连接(每秒约1000个连接),直到总连接数达到CONNECTIONS,每个连接都会睡眠[1, KEEPALIVE / 2]的一个随机数(单位为秒),然后向服务端url发送一个HEAD请求来维持HTTP KeepAlive,然后重复上一个睡眠步骤。。。
与客户端1完全一致,除了IP为10.211.55.10
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 1723336 11624 76124 0 0 62 1 26 28 0 0 100 0 0
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 1681552 11868 76840 0 0 50 1 24 25 0 0 100 0 0
3. 客户端1和2先后启动,每个客户端发起50000个长连接,并维持直到服务端关闭或超时。
(pyvenv) $ python -c 50000 -k 3600 &
# curl
Active connections: 100001
server accepts handled requests
Reading: 0 Writing: 1 Waiting: 100000
# ps -p 1899 -o pid,%cpu,%mem,rss,comm
PID %CPU %MEM RSS COMMAND
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 654248 62920 158924 0 0 6 6 361 108 0 1 98 0 0
0 0 0 654232 62920 158952 0 0 0 85 804 218 0 1 98 0 0
0 0 0 654108 62928 158976 0 0 0 9 813 214 0 1 98 0 0
0 0 0 654108 62928 159004 0 0 0 0 803 220 0 1 99 0 0
total used free shared buffers cached
Mem: 1918576 1264576 654000 0 62952 159112
-/+ buffers/cache: 1042512 876064
1. NGINX平均每个连接的内存占用很小,通过ps的rss看出,每个连接物理内存占用约1k。多数内存都被内核TCP缓存占用。 2. NGINX维持大量连接(少量活跃连接,本文中平均每秒活跃连接为总连接数的千分之一)占用很少CPU,上文仅为2%。 3. 最好的优化就是不优化。整个测试除了提升文件数和连接数的这些硬限制外,没有任何参数调优,但仔细计算下就发现平均每个连接内存占用不到10k,远小于默认的缓存大小(net.ipv4.tcp_rmem = 4096 87380 4194304)和 (net.ipv4.tcp_wmem = 4096 16384 4194304) 4. NGINX维持此类连接的主要瓶颈就是可用内存大小,我的2GB内存虚拟机其实可以支持15万长连接,只不过我物理机器没有内存再继续clone虚拟机客户端了:-( 5. 虽然会遇到更多内核参数的限制,但大内存服务器支持100万连接是完全没问题的。