NGINX轻松管理10万长连接

一 前言
 
当管理大量连接时,特别是只有少量活跃连接,NGINX有比较好的CPU和RAM利用率,如今是多终端保持在线的时代,更能让NGINX发挥这个优点。本文做一个简单测试,NGINX在一个普通PC虚拟机上维护100k的HTTP长连接,然后查看NGINX和系统的资源利用率。
 
二 测试环境
 
1.服务端
 
硬件:双核2.3GHz,2GB内存
软件:CentOS 6.5, kernel 2.6.32,  gcc 4.4.7, nginx 1.4.7
IP:10.211.55.8
 
内核参数调整:
$ /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;
events {
    worker_connections  102400;
}
http {
       # 设一个比较大得超时,客户端能以平缓的方式发送HEAD请求来维持KeepAlive
       keepalive_timeout  3600;
 
        #监控连接数,本机访问
        location /nginx_status {
            stub_status on;
            access_log   off;
            allow 127.0.0.1;
            deny all;
        }
}
 
 
2. 客户端1
 
硬件:双核2.3GHz,2GB内存
软件:CentOS 6.5, kernel 2.6.32, gcc 4.4.7, Python 3.3.5
IP:10.211.55.9
 
内核参数调整:
$ /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
 
Python 3.3.5从源码编译,如下配置:
$ pyvenv ~/pyvenv #创建虚拟环境,便于测试
$ . ~/pyvenv/bin/activate #激活虚拟环境
(pyvenv) $ python get-pip.py #从pip官网下载get-pip.py
(pyvenv) $ pip install asyncio #安装异步IO模块
 
因为Apache ab只能批量请求,不能维持连接,所以自己写了一个HTTP长连接测试工具asyncli.py,详细实现见http://blog.chinaunix.net/uid-190176-id-4223282.html
基本用法:
(pyvenv) $ python asyncli.py --help
usage: asyncli.py [-h] [-c CONNECTIONS] [-k KEEPALIVE] url
 
asyncli
 
positional arguments:
  url                   page address
 
optional arguments:
  -h, --help            show this help message and exit
  -c CONNECTIONS, --connections CONNECTIONS
                        number of connections simultaneously
  -k KEEPALIVE, --keepalive KEEPALIVE
                        HTTP keepalive timeout
 
工作机制:
每隔10毫秒连续创建10个连接(每秒约1000个连接),直到总连接数达到CONNECTIONS,每个连接都会睡眠[1, KEEPALIVE / 2]的一个随机数(单位为秒),然后向服务端url发送一个HEAD请求来维持HTTP KeepAlive,然后重复上一个睡眠步骤。。。
 
3. 客户端2
 
与客户端1完全一致,除了IP为10.211.55.10
 
三 运行与输出
 
1. 服务端系统空闲
# vmstat
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
 
2. 服务端启动NGINX,无外部WEB请求
# nginx
# vmstat
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 asyncli.py -c 50000 -k 3600 http://10.211.55.8/ &
 
4. 约2小时后。。。查看服务端
# curl http://127.0.0.1/nginx_status
Active connections: 100001
server accepts handled requests
 165539 165539 1095055
Reading: 0 Writing: 1 Waiting: 100000
 
# ps -p 1899 -o pid,%cpu,%mem,rss,comm
  PID %CPU %MEM   RSS COMMAND
 1899  2.0  4.9 94600 nginx
 
# vmstat 3
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    
^C
 
# free
             total       used       free     shared    buffers     cached
Mem:       1918576    1264576     654000          0      62952     159112
-/+ buffers/cache:    1042512     876064
Swap:      4128760          0    4128760
 
四 总结
 
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万连接是完全没问题的。 
posted on 2015-08-04 17:56  blogsheng  阅读(1817)  评论(0编辑  收藏  举报