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