Nginx HTTP Push
前些天看到一个Nginx的Module,用来是实现Comet,今天简单试了一下功能。作者名叫Leo Ponomarev,项目地址:http://pushmodule.slact.net/
安装
Module需要在编译时加入nginx,同时下载nginx和nginx-push-module,在nginx configure时增加一个参数:
./configure –add-module=path/to/nginx_http_push_module
使用
编写一个非常基本的nginx配置文件:
events{
worker_connections 1024;
}
http{
server {
listen 80;
server_name localhost;
location /publish {
set $push_channel_id $arg_id;
push_publisher;
push_store_messages on;
push_message_timeout 2h;
push_max_message_buffer_length 10;
push_min_message_recipients 0;
}
location /subscribe{
push_subscriber;
push_subscriber_concurrency broadcast;
set $push_channel_id $arg_id;
default_type text/plain;
}
}
}
一个简单的Server定义了两个路径分别用于publish和subscribe。所有相关的配置项可以在项目主页找到解释,不作赘述。
启动nginx
nginx -c /home/sun/nginxpush/nginx-push.conf
打开一个终端访问subscribe
curl -X GET http://localhost/subscribe?id=0
可以看到HTTP请求被阻塞
打开另一个终端访问publish
curl -X POST http://localhost/publish?id=0 -d “Hello World”
此时subscriber收到字符串”Hello World” ,完成HTTP请求。
subscriber可以通过设置HTTP头来对消息进行过滤,如
curl -X POST http://localhost/publish?id=0 -d “Hello World”
curl -X GET http://localhost/subscribe?id=0 –verbose
HelloWorld
从响应的头部可以看到Last-Modified: Thu, 26 Nov 2009 09:44:59 GMT的时间是上一次publish的时间,并且通过Vary字段提示了两个选项
- If-None-Match
- If-Modified-Since
RFC中对Vary头是这样解释的:
The Vary field value indicates the set of request-header fields that fully determines, while the response is fresh, whether a cache is permitted to use the response to reply to a subsequent request without revalidation.
即可以通过发送If-Modified-Since来获取指定时间之后的数据
curl -X GET -H “If-Modified-Since: Thu, 26 Nov 2009 09:44:50 GMT” http://localhost/subscribe?id=0 –verbose
这时subscribe会重新被阻塞而不是接收上次publish的数据,充分利用了HTTP的语义。
这样用push module来做Web-IM、聊天室的思路就非常清晰了:每个浏览器保持一个subscriber连接,在接收到消息后连接关闭。把消息打印出来,并根据消息响应的头部Last-Modified请求重新subscribe。
Moontools的APE也是Server Pull
@goodtiger, 这类技术如果不是客户端轮询的话应该都需要服务器端支持长连接,仅仅浏览器端不太好实现。。。
我听说还有利用Flash做的
另外HTML5里面有个WebSocket,可能是对这一类功能有一个比较好的封装
HTML5里一些新功能真变态,都可以在客户端写数据库了