使用swoole的Process实现生产者消费者模型
来源:互联网 发布:怎么下载网络视频 编辑:程序博客网 时间:2024/05/22 08:05
零.源码
<?phpabstract class Schedule{ protected $_consumerList = array(); protected $_msgqkey = null; protected $_consumerNum = 2; protected $_finishFlag = 'ALLDONE'; public function __construct($cNum = 0){ if ($cNum){ $this->_consumerNum = $cNum; } } public function setConsumerNum($num = 0){ if ($num){ $this->_consumerNum = $num; return true; } return false; } public function setFinishFlag($flag = null){ if ($flag){ $this->_finishFlag = $flag; return true; } return false; } public function run(){ $this->_consumerList = array(); for($i=0; $i<$this->_consumerNum; $i++){ $consumer = new swoole_process(function($worker){ $this->_consumerFunc($worker); }); if ($this->_msgqkey){ $consumer->useQueue($this->_msgqkey); } else{ $consumer->useQueue(); } $pid = $consumer->start(); $this->_consumerList[$pid] = $consumer; } $producer = new swoole_process(function($worker){ //echo "i'm passer\n"; exit(0); }); if ($this->_msgqkey){ $producer->useQueue($this->_msgqkey); } else{ $producer->useQueue(); } $pid = $producer->start(); echo "begin:\n"; echo sprintf("msgqkey:%s\n", $producer->msgQueueKey); $this->_producerFunc($producer); } protected function _producerFunc($worker){ if ($this->_onlyConsume()){ return; } foreach ($this->doProduce($worker) as $data){ $worker->push($data); } //任务数据被取完 while(true){ $c = $worker->statQueue(); $n = $c['queue_num']; if ($n === 0){ break; } } //放入consumer进程程结束标识 foreach($this->_consumerList as $pid => $w){ $w->push($this->_finishFlag); } //确认结束 while(true){ $c = $worker->statQueue(); $n = $c['queue_num']; if ($n === 0){ break; } } $worker->freeQueue(); } protected function _consumerFunc($worker){ while(1){ $data = $worker->pop(); $pid = $worker->pid; if ($data == $this->_finishFlag){ echo "consumer $pid exit\n"; $worker->exit(0); } else{ $this->doConsume($data, $worker); } } } protected function _onlyConsume(){ return !! $this->_msgqkey; } abstract protected function doProduce($worker); abstract protected function doConsume($data, $worker);}
一.功能说明
- 实现了生产者消费者模型,一个生产者向任务队列写数据,N个消费者取数据做处理。
- 数据处理完后生产者与消费者自动退出
- 在消费者意外挂掉的情况下,允许单独运行消费者继续处理之前队列中的任务
二.使用说明
1. 生产者消费者demo
<?phpclass Taskdemo extends Schedule{ protected $_consumerNum = 5; protected function doProduce($worker){ $all = 100; for($i=0; $i<$all; $i+=4){ yield json_encode(array('data'=>$i)); } } protected function doConsume($data, $worker){ //your process sleep(1); echo "consumer:{$worker->pid} redv {$data}\n"; }}
说明
1. 要继承Schedule
2. _consumerNum为消费者个数,不设置,默认2个。
3. doProduce($worker)用于产生任务数据的函数,要求返回值必须是数组或迭代器,每一项为一条任务数据。$worker为swoole进程句柄。
4. doConsume($data,$worker)用于消费者处理数据的函数。$data为单条消息,$worker为swoole进程句柄。
5. 一般情况进程句柄$worker都不会用到,可以忽略
2. 处理程序中途挂掉的情况
步骤:
1.确认当前队列的key
程序运行时,会打出
msgqkey:1078263
也可以使用命令行
ipcs -q------ Message Queues --------key msqid owner perms used-bytes messages 0x001073f7 2359298 ballqiu 666 165 15
key值即是所需要的
- 修改Taskdemo,加入一行代码
protected $_msgqkey = 0x001073f7;
- 重新运行程序
- 手动删除队列
ipcrm -q $msgqkey
三.实现原理
- 使用swoole的Process,主进程调用doProduce()向消息队列写任务数据,fork出的n个子进程从队列取数据。队列就是linux用于进程间通信的消息队列。
- 子进程从队列里不停取任务处理,如果拿到“完成标识串”(一个特定字符串),就退出。
- 主进程发现队列数据被处理完后,如果有n个子进程,就向队列发n个到“完成标识串”。然后再次检查队列,队列空时删除队列,自身退出。
四.注意事项
- 消息队列的一些使用上的限制,可以参见这里
- 默认的”完成标识串”是ALLDONE,如需修改,可在Taskdemo中增加
protected $_finishFlag = 'youflag';
0 0
- 使用swoole的Process实现生产者消费者模型
- 使用swoole实现生产者消费者模型(2)
- 生产者消费者模型的实现
- 生产者消费者模型的实现
- 使用semaphore实现生产者-消费者简单模型
- 使用semaphore实现生产者-消费者简单模型
- 使用BlockingQueue实现生产者和消费者模型
- 生产者-消费者模型实现
- 生产者-消费者模型的Java实现
- 生产者-消费者模型的Java实现
- 生产者-消费者模型的java实现
- [多线程] 生产者消费者模型的BOOST实现
- golang 的 channel 实现 生产者/消费者 模型
- 生产者-消费者模型的Java实现
- 生产者-消费者模型的Java实现
- 基于QT实现的生产者消费者模型
- 基于JAVA实现的生产者消费者模型
- PyQt实现的生产者消费者模型
- .net将一个DataTable拆分成n个DataTable
- iOS适配问题---用2@图和3@图怎么是使用
- Fbx文件解析(一)——FBX SDK for Windows环境配置
- 初学java:Map集合的编历
- python爬虫抓取-helloworld
- 使用swoole的Process实现生产者消费者模型
- 2017年 “印度制造”的iPhone就能够面世了?
- Elasticsearch 管理文档
- Oracle常用维护SQL汇总
- Myeclipse启动tomcat的debug模式,总是跳到Class.class里面报错
- springboot(七)redis 实现session共享
- 一个使用MongoDB和Fuse开发的虚拟文件系统
- js继承的原理
- Oracle 触发器详解