基于http协议搭建各种服务已经成为一种大势,但是基于http协议的客户端和服务器端的交互却是个难题,没办法http协议天生如此,其是无状态的协议,每次交互建立链接,结束断开.
客户端和服务器交互很简单,请求描述功能接口的url即可,带上参数.可是服务器要和客户端交互,那就有些困难.下面是几种方法.
1.客户端轮询,最差的一种,客服端和服务器端都在白忙活,浪费资源.
2.long-polling,长轮询,客户端和服务器端保持一个链接,客户端主动发起一个链接,没有如果服务器端没有数据发送給客户端,链接保持,直到服务器有数据发送給客户端,客户端接收数据,断开链接.客户端再链接服务器,进入下一个周期.这就是服务器push.
nginx是一款优秀的web服务器和反响代理服务器,其在同时并发连接方面性能优异,那么其作为hold住大量客服端服务器再合适不过.
nginx_http_push_module(NHPM)模块可以将你的nginx打造成一个Comet Server.
NHPM提供两个antor,一个是publisher,消息发布者,一个是subscriber,客户端,联系他们的关系是channel,频道.
这是一个大致的简图.
安装NHPM,在编译nginx是使用add-module将下载的模块添加进来,官网为https://pushmodule.slact.net.
这是我的编译参数:
./configure --with-http_gzip_static_module --with-http_ssl_module --with-http_stub_status_module --with-http_gunzip_module --with-http_realip_module --add-module=/home/zhou/software/nginx-1.7.6/module/nginx_http_push_module-0.73
编译的过程中可以会报错,是编译的报警参数严格就会当成错误,主要是一个变量没有初始化.将ngx_http_push_module.c的673行的buf_use_count赋值为NULL就可以了.然后make && sudo make install,默认安装到/usr/local/nginx.
安装成功之后,我们就需要配置我们的NHPM.阅读模块的README文件,其有关于配置参数的详细的说明,protocl.txt有详细的关于其实现的long-polling的说明.test目录提供了相关的配置例子.
下面是我的配置:
在server 80下配置了两个location
location /pub {
set $push_channel_id $arg_id;
push_publisher;#角色
push_store_messages on; #打开消息队列
push_max_message_buffer_length 20;#长度
push_message_timeout 2h;#过期时长
}
location /sub {
push_subscriber;#角色
push_subscriber_concurrency broadcast;#广播的形式
set $push_channel_id $arg_id;
default_type text/plain;
}
写了个python,脚本最为客户端,写了个页面作为消息发布
import httplib def subscriber(**opts): while True: con = httplib.HTTPConnection("localhost") con.request('GET', '/sub?id=' + opts['channel'], headers = opts['head']) re = con.getresponse(); print re.read() print re.getheader('Last-Modified') opts['head']['If-Modified-Since'] = re.getheader('Last-Modified') subscriber(channel = 'miss', head = {'If-Modified-Since':''})
接收到一条消息后,重新建立连接是将得到的回复中的
LAST_MODIFIED值传给发送头中的<pre><code class="language-ruby" data-lang="ruby"><span class="s1">If-Modified-Since'</span></code>
其是根据这个来判断消息新旧的时序.现在运行这个脚本其会报No channel id provided,我们的channel是miss,这是因为我们没有向这个频道push,其在第一次push会创建.push的页面
<form action="http://localhost/pub?id=miss" method="post"> Message: <input name="a" type="text"/> <input name="" type="submit" value="Push" /> </form>
很简单.我们要firefox打开它
然后按下push,提交,得到如下的返回
说明miss channel创建成功,现在没有一个subscriber,现在运行python脚本
其答应了一条消息,然后就阻塞等待回复,这是我们在push一条数据.
其又接收一条然后阻塞等待,这样实现了服务器发送数据給客户端.基于这个我们可以搭建如下简单的一个控制系统.
NHPM负责控制消息的发布,Logic server完成相应的业务功能.