Http Server Push是一种推送技术,服务器主动向浏览器发送数据。
1. 下载安装
1) 下载源代码包
Nginx:http://nginx.org/
Nginx Http Push Module:http://pushmodule.slact.net/
2) 解压缩
tar zxvf nginx-1.0.14.tar.gz
tar zxvf nginx_http_push_module-0.692.tar.gz
3) 编译安装
编译Nginx,configure指定待添加模块的路径
./configure --add-module=path/to/nginx_http_push_module ...
make && make install
2. 配置
关于推送配置说明,可参考推送模块源码包内的README,
推送协议可参考protocol.txt,或访问http://pushmodule.slact.net/protocol.html,
在Nginx配置文件中添加一个基本的推送配置,
可参考自带的用于测试的配置文件nginx_http_push_module-0.692/tests/nginx.conf,将其中配置部分附加到Nginx配置文件的http结构中:
server {
listen 8082;
location / {
location = /sub {
set $push_channel_id $arg_id;
push_subscriber;
push_subscriber_concurrency broadcast;
push_channel_group broadcast;
}
location = /pub {
set $push_channel_id $arg_id;
push_publisher;
push_min_message_buffer_length 5;
push_max_message_buffer_length 20;
push_message_timeout 5s;
push_channel_group broadcast;
}
}
}
3. 调试
启动Nginx,使用curl进行推送测试
1) subscriber请求数据:
curl -X GET localhost:8082/sub?id=1
向channel1请求数据,当前channel无数据,等待数据生成
2) publisher推送数据:
curl -X POST -d "data_to_push" localhost:8082/pub?id=1
向channel1推送数据,subscriber收到数据并返回
4. 总结
Http服务器需要使用一个或一组url指定发布服务和订阅服务(publisher and subscriber locations,我翻译的不太合理)。
所有发送到发布服务的请求被视为发布请求,所有发送到订阅服务的请求被视为订阅请求。
通道(channel)需要使用唯一id进行标识,推荐使用url指定具体通道,如 localhost:8082/sub?id=1。
发布请求(publisher request)通过POST向服务器传输数据,并通知其向某些通道某些用户发送数据,
订阅请求(subscriber request)通过GET向服务器请求数据,通知其该用户想要接收数据。
附上一个Python脚本
#!/usr/bin/python
#
# file : nginx_http_push.py
# author: caosiyang
#
import httplib
#send publisher request
def publish(host, url, data_to_push):
'''Send publisher request.
description: push data.'''
pubconn = httplib.HTTPConnection(host)
pubconn.request('POST', url, data_to_push)
pubconn.close()
#send subscriber request
def subscribe(host, url, header):
'''Send subscriber request.
description: receive data.'''
subconn = httplib.HTTPConnection(host)
subconn.request('GET', url, '', header)
resp = subconn.getresponse()
last_modified = ''
etag = ''
if resp.status == 200:
header = resp.getheaders()
for item in header:
if (item[0] == 'last-modified'):
last_modified = item[1]
continue
if (item[0] == 'etag'):
etag = item[1]
continue
#print 'last-modified: %s' % last_modified
#print 'etag : %s' % etag
#print 'receive data : %s' % resp.read()
#print ''
print 'last-modified: %s\n' \
'etag : %s\n' \
'receive data : %s\n' % (last_modified, etag, resp.read())
subconn.close()
return (last_modified, etag)
#script starts
host = 'localhost:8082'
for i in range(0, 10):
publish(host, '/pub?id=1', 'test_data_%d' % i)
header = {'If-Modified-Since': '', 'If-None-Match': ''}
for i in range(0, 10):
tuple = subscribe(host, '/sub?id=1', header)
header['If-Modified-Since'] = tuple[0]
header['If-None-Match'] = tuple[1]
其输出如下
last-modified: Thu, 05 Apr 2012 04:55:29 GMT
etag : 0
receive data : test_data_0
last-modified: Thu, 05 Apr 2012 04:55:29 GMT
etag : 1
receive data : test_data_1
last-modified: Thu, 05 Apr 2012 04:55:29 GMT
etag : 2
receive data : test_data_2
last-modified: Thu, 05 Apr 2012 04:55:29 GMT
etag : 3
receive data : test_data_3
last-modified: Thu, 05 Apr 2012 04:55:29 GMT
etag : 4
receive data : test_data_4
last-modified: Thu, 05 Apr 2012 04:55:29 GMT
etag : 5
receive data : test_data_5
last-modified: Thu, 05 Apr 2012 04:55:29 GMT
etag : 6
receive data : test_data_6
last-modified: Thu, 05 Apr 2012 04:55:29 GMT
etag : 7
receive data : test_data_7
last-modified: Thu, 05 Apr 2012 04:55:29 GMT
etag : 8
receive data : test_data_8
last-modified: Thu, 05 Apr 2012 04:55:29 GMT
etag : 9
receive data : test_data_9