前不久偶尔发现nginx一个实现服务器推的模块NGiNX_HTTP_Push_Module,尝试了一下,可以轻松实现服务器推,而且由于nginx服务器自身是采用事件驱动而非线程模型提供服务,可以保证高并发低延迟的特点。
首先下载nginx_http_push_module模块安装
./configure –add-module=path/to/nginx_http_push_module …
make
make install
修改nginx.conf配置文件,这里我尽量简化模块指令的配置
location /publish { set $push_channel_id $arg_id; push_publisher; #发布者 } location /activity { push_subscriber; #订阅者 set $push_channel_id $arg_id; }
然后启动nginx,一切工作完毕,来测试一下nginx的“发布-订阅”功能吧。
打开浏览器访问http://localhost/activity?id=10000,我们可以看到服务器端维持了这个长连接,并不返回内容或者任何4xx,5xx的http状态码。
(其中id=10000表示通道号,“id”是$arg_id变量去掉前缀后的名称)
编辑perl脚本
#!/usr/bin/perl use LWP::UserAgent; use HTTP::Request::Common; my $ua = new LWP::UserAgent; my $response = $ua->request( POST 'http://127.0.0.1//publish?id=10000', Content_Type => 'text/html', Content => 'hi,i posted a message' ); my $content = $response->content; print $content;
保存并执行perl脚本向指定通道发布消息,然后我们可以看到浏览器接收到订阅通道的消息’hi,i posted a message’。
做完上面的实验,我们再来看看模块的具体的命令:
-
首先是push_subscriber [ long-poll | interval-poll ]指定订阅者角色,默认选择长轮询long-poll,如果指定interval-poll,则服务器端会在订阅通道没有消息时立即返回304Not
Modified状态。 - 可以通过配置push_subscriber_concurrency [ last | first | broadcast ] 控制订阅者获取通道消息的顺序,默认是“广播”方式,last表示通道保持最后一个长连接,其它长连接返回409冲突错误。
-
还有其它控制通道消息的指令
- push_store_messages [ on | off ],是否保存发布的消息
- push_max_reserved_memory [ size ] ,存储消息空间大小
- push_message_timeout [ time ],消息过期时间
- 其它指令可以参照模块的使用手册
测试一:我们来做个简单的压力测试并发的效果,在10000通道没有消息队列时,用apache自带工具模拟并发500的测试,然后查看vmstat,可以看到系统内存和cpu都没有被占用,只是磁盘IO有所变化,存在写磁盘,随即恢复正常
vm6245:/usr/sbin # ab2 -c 500 -n 10000 http://localhost/activity?id=10000
vm6245:~/penjin # vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- -----cpu------ r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 12312 317364 19056 17480 0 0 0 3 8 5 0 0 100 0 0 0 0 12312 317364 19116 17420 0 0 0 60 38 14 0 0 99 1 0 0 0 12312 317372 19116 17420 0 0 0 0 17 9 0 0 100 0 0 0 0 12312 317372 19116 17420 0 0 0 0 19 7 0 0 100 0 0
测试二:而当通道有了消息发布后,再通过ab测试结果如下
vm6245:/usr/sbin # ab2 -c 500 -n 10000 http://localhost/activity?id=10000 This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0 Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Copyright 2006 The Apache Software Foundation, http://www.apache.org/ Benchmarking localhost (be patient) Completed 1000 requests Completed 2000 requests Completed 3000 requests Completed 4000 requests Completed 5000 requests Completed 6000 requests Completed 7000 requests Completed 8000 requests Completed 9000 requests Finished 10000 requests Server Software: nginx/1.1.13 Server Hostname: localhost Server Port: 80 Document Path: /activity?id=10001 Document Length: 21 bytes Concurrency Level: 500 Time taken for tests: 1.191773 seconds Complete requests: 10000 Failed requests: 0 Write errors: 0 Total transferred: 2580000 bytes HTML transferred: 210000 bytes Requests per second: 8390.86 [#/sec] (mean) Time per request: 59.589 [ms] (mean) Time per request: 0.119 [ms] (mean, across all concurrent requests) Transfer rate: 2113.66 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 24 22.4 18 74 Processing: 6 30 11.8 36 46 Waiting: 0 13 8.8 11 34 Total: 8 54 32.5 53 117 Percentage of the requests served within a certain time (ms) 50% 53 66% 71 75% 82 80% 88 90% 101 95% 107 98% 112 99% 113 100% 117 (longest request)
vm6245:~/penjin # vmstat 1 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 12312 319588 20696 20000 0 0 0 3 8 5 0 0 100 0 0 3 0 12312 310776 20700 20516 0 0 0 0 198 23935 10 20 70 0 0 0 0 12312 314864 20820 21176 0 0 0 1244 524 15876 11 31 56 4 0 0 0 12312 315484 20820 21176 0 0 0 0 28 15 0 0 100 0 0 0 0 12312 315484 20820 21176 0 0 0 0 20 6 0 0 100 0 0 0 0 12312 315656 20820 21176 0 0 0 0 19 12 0 0 100 0 0
我们主要关注测试一的结果,系统在维持长连接的时候cpu,内存,磁盘IO的压力都不大。网上有人说到NGiNX_HTTP_Push_Module模块存在内存问题,因为保持长连接的内存没有适时得到释放,但在我的测试中看不出来,不知道这种说法是否属实。