用Gearman做队列来实现消息推送

浏览:
字体:
发布时间:2013-12-09 23:23:24
来源:

前面有一篇文章,是Nginx+Lua来实现推送的方式,这里我们换一种作法,用Apache+Gearman作队列来实现。


此方案的主要思路是这样的:

客户端不会频繁的轮询服务端,而是对服务端发起一个长连接,服务端通过阻塞方式读取Gearman队列数据,一旦发现新数据便给客户端发出响应,这次交互便结束了。客户端处理好新数据后再重新发起一个长连接,如此周而复始。

MySQL安装gearman-mysql-udf插件,数据首先是被插入MySQL的表中,MySQL利用触发器调用gearman-mysql-udf函数,将数据写入Gearman,对于Gearman来说,MySQL这边是Client。

接下来,Apache不会再去轮询数据库,而是改为读取Gearman,对于Gearman来说,Apache是Worker,Worker读取队列数据是以阻塞方式时行的,如果有新数据但读出并给客户端发出响应,没有则一直阻塞到超时。Apache做为Gearman的Worker,当读取消息被阻塞时,连接是一直存在的,因些这种方案里,Apache与Gearman会维持大量长连。


注:服务端维持大量长连接时内核参数的调整请参考:http长连接200万尝试及调优。


具体应该需求、实现方法及代码如下


这个应用情况是这样的:
有一个门禁刷卡数据表(已经在用)
现要求针对一些特殊的人,门禁刷卡后,要求在一个液晶屏上显示一些欢迎信息,欢迎信息要及时显示

为不影响现有系统,我们采用一个外挂的形式,新增刷卡记录后,通过触发器将数据插入Gearman队列,浏览器通过Ajax长轮循的方式访问Apache,Apaceh通过PHP连接Gearman,以阻塞读的方式读出记录

对于Gearman来说,MySQL是Client,即生产者,产生队列数据,PHP是Worker,即消费者,取出队列数据


为了让MySQL能将数据传入Gearman,这里使用了lib_mysqludf_json和gearman-mysql-udf的组合,这两个库的安装方法可以参见我的另一篇文章《Gearman分布式任务处理系统(二)扩展应用》


门禁刷卡记录表:

CREATE TABLE `vdooropen` (  `vid` int(11) NOT NULL AUTO_INCREMENT,  `doorno` int(11) NOT NULL,  `rfsim` char(16) NOT NULL,  `optime` char(15) NOT NULL,  `ynopen` char(1) NOT NULL,  PRIMARY KEY (`vid`),  UNIQUE KEY `vdooropen_I0` (`vid`),  KEY `vdooropen_i1` (`doorno`,`rfsim`)) ENGINE=InnoDB;DELIMITER $$CREATE TRIGGER t_vopendoor AFTER INSERT ON vdooropen  FOR EACH ROW BEGIN    SET @ret=gman_do_background('getmsg', json_object(NEW.vid as 'vid',NEW.doorno as 'doorno',NEW.rfsim as 'rfsim',NEW.optime as 'optime', NEW.ynopen as 'ynopen'));   END$$DELIMITER ;

前端浏览器页面getmsg.html
无标题文档<script language="JavaScript" type="text/javascript" src="./prototype.js"></script><script language="JavaScript">  var Class = {    create: function() {      return function() {        this.initialize.apply(this, arguments);      }    }  }  var Comet = Class.create();  Comet.prototype = {      maxvid: 0,      url: './backend.php',      noerror: true,      initialize: function(){      },      connect: function(){          this.ajax = new Ajax.Request(this.url, {              method: 'get',              parameters: {                  'maxvid': this.maxvid              },              onSuccess: function(transport){                  var response = transport.responseText.evalJSON();                  this.comet.maxvid = response['vid'];                  this.comet.handleResponse(response);                  this.comet.noerror = true;              },              onComplete: function(transport){                  if (!this.comet.noerror) setTimeout(function(){                                           comet.connect()                                           }, 5000);                  else                  this.comet.connect();                  this.comet.noerror = false;              }          });          this.ajax.comet = this;      },      handleResponse: function(response){          $('content').innerHTML += '
' + response['vid'] + ',' + response['doorno'] + ',' + response['rfsim'] + ',' + response['optime'] + ',' + response['ynopen'] + '
'; } } var comet = new Comet(); comet.connect();</script>

后端PHP脚本backend.php

 "."maxvid: ".$maxvid."/n", 3 , "/usr/local/apache2219/logs/php_log");$gmworker = new GearmanWorker();$gmworker->addServer();$gmworker->addFunction("getmsg", "getmsg");if ( ($gmworker->work()) && ($gmworker->returnCode() == GEARMAN_SUCCESS) ){  error_log(date("[Y-m-d H:i:s]")." < ".$msg."/n", 3 , "/usr/local/apache2219/logs/php_log");  echo $msg;  flush();}function getmsg($job){  global $msg;  $msg = $job->workload();  $result = "OK";  return $result;}?>


>更多相关文章
24小时热门资讯
24小时回复排行
资讯 | QQ | 安全 | 编程 | 数据库 | 系统 | 网络 | 考试 | 站长 | 关于东联 | 安全雇佣 | 搞笑视频大全 | 微信学院 | 视频课程 |
关于我们 | 联系我们 | 广告服务 | 免责申明 | 作品发布 | 网站地图 | 官方微博 | 技术培训
Copyright © 2007 - 2024 Vm888.Com. All Rights Reserved
粤公网安备 44060402001498号 粤ICP备19097316号 请遵循相关法律法规
');})();