用Gearman做队列来实现消息推送
来源:互联网 发布:大数据培训课程哪家好 编辑:程序博客网 时间:2024/05/05 20:38
前面有一篇文章《实现一个简单的服务端推方案》,是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
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312" /><title>无标题文档</title><script language="JavaScript" type="text/javascript" src="./prototype.js"></script></head><body><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 += '<div>' + response['vid'] + ',' + response['doorno'] + ',' + response['rfsim'] + ',' + response['optime'] + ',' + response['ynopen'] + '</div>'; } } var comet = new Comet(); comet.connect();</script><div id="content"></div></body></html>
后端PHP脚本backend.php
<?phpheader("Cache-Control: no-cache, must-revalidate");header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");flush();//控制浏览器前端不要缓存结果,每次都要重新查询$maxvid = $_GET["maxvid"];error_log(date("[Y-m-d H:i:s]")." > "."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;}?>
- 用Gearman做队列来实现消息推送
- 用php做消息推送
- 用php做消息推送
- php做推送服务端实现ios消息推送
- php做推送服务端实现android消息推送
- php做推送服务端实现ios消息推送
- php做推送服务端实现android消息推送
- php做推送服务端实现ios消息推送
- 用redis来实现具有ack机制的消息队列
- 用redis做消息队列
- 利用消息队列来实现IPC
- 利用消息队列来实现IPC
- 构建基于redis+gearman+nodejs 的消息推送系统
- 用androidpn来实现推送
- 用androidpn来实现推送
- 用androidpn来实现推送
- 用androidpn来实现推送
- 用androidpn来实现推送
- Memory驱动——测试程序
- PhoneGap 学习资料汇总
- cocos2dx之如何实现自己的sprite
- Edmonds Karp 算法
- 数据结构比看---排序算法总结
- 用Gearman做队列来实现消息推送
- ocr样本训练
- Kruskal求两点之间边权值最小的边+Uva10048
- 数组排序(冒泡法 b)
- Cacti命令行添加监控详解(转)
- 转储控制文件
- hbase 详解
- Memcached Timed out(1000) waiting for operation
- pip和easy_install使用方式