设为首页 收藏本站
查看: 647|回复: 0

[经验分享] PHP高级编程之消息队列

[复制链接]

尚未签到

发表于 2017-4-2 10:44:22 | 显示全部楼层 |阅读模式
PHP高级编程之消息队列



http://netkiller.github.io/journal/php.mq.html




Mr. Neo Chen (陈景峰), netkiller, BG7NYT

  中国广东省深圳市龙华新区民治街道溪山美地
518131
+86 13113668890
+86 755 29812080
<netkiller@msn.com>









版权声明
  转载请与作者联系,转载时请务必标明文章原始出处和作者信息及本声明。


DSC0000.png




文档出处:
http://netkiller.github.io
http://netkiller.sourceforge.net


DSC0001.jpg



  微信扫描二维码进入 Netkiller 微信订阅号
  读者群:128659835 请注明“读者”






2015-10-20



摘要





我的系列文档

Netkiller Architect 手札Netkiller Developer 手札Netkiller PHP 手札Netkiller Python 手札Netkiller Testing 手札
Netkiller Cryptography 手札Netkiller Linux 手札Netkiller Debian 手札Netkiller CentOS 手札Netkiller FreeBSD 手札
Netkiller Shell 手札Netkiller Security 手札Netkiller Web 手札Netkiller Monitoring 手札Netkiller Storage 手札
Netkiller Mail 手札Netkiller Docbook 手札Netkiller Project 手札Netkiller Database 手札Netkiller PostgreSQL 手札
Netkiller MySQL 手札Netkiller NoSQL 手札Netkiller LDAP 手札Netkiller Network 手札Netkiller Cisco IOS 手札
Netkiller H3C 手札Netkiller Multimedia 手札Netkiller Perl 手札Netkiller Amateur Radio 手札Netkiller DevOps 手札
  您可以使用iBook阅读当前文档










目录


  • 1. 什么是消息队列
  • 2. 为什么使用消息队列
  • 3. 什么场合使用消息队列
  • 4. 什么时候使用消息队列
  • 5. 谁负责处理消息队列

  • 6. 怎么实现消息队列框架

    • 6.1. 守护进程
    • 6.2. 消息队列协议
    • 6.3. 消息队列处理
    • 6.4. 测试


  • 7. 总结
  • 8. 延伸阅读



1. 什么是消息队列






  消息队列(英语:Message queue)是一种进程间通信或同一进程的不同线程间的通信方式

2. 为什么使用消息队列






  消息队列技术是分布式应用间交换信息的一种技术。消息队列可驻留在内存或磁盘上,队列存储消息直到它们被应用程序读出。通过消息队列,应用程序可独立地执行,它们不需要知道彼此的位置、或在继续执行前不需要等待接收程序接收此消息。

3. 什么场合使用消息队列






  你首先需要弄清楚,消息队列与远程过程调用的区别,在很多读者咨询我的时候,我发现他们需要的是RPC(远程过程调用),而不是消息队列。
  消息队列有同步或异步实现方式,通常我们采用异步方式使用消息队列,远程过程调用多采用同步方式。
  MQ与RPC有什么不同? MQ通常传递无规则协议,这个协议由用户定义并且实现存储转发;而RPC通常是专用协议,调用过程返回结果。

4. 什么时候使用消息队列






  同步需求,远程过程调用(PRC)更适合你。
  异步需求,消息队列更适合你。
  目前很多消息队列软件同时支持RPC功能,很多RPC系统也能异步调用。

消息队列用来实现下列需求


  •   存储转发

  •   分布式事务

  •   发布订阅

  •   基于内容的路由

  •   点对点连接




5. 谁负责处理消息队列






  通常的做法,如果小的项目团队可以有一个人实现,包括消息的推送,接收处理。如果大型团队,通常是定义好消息协议,然后各自开发各自的部分, 例如一个团队负责写推送协议部分,另一个团队负责写接收与处理部分。
  那么为什么我们不讲消息队列框架化呢?

框架化有几个好处:


  • 开发者不用学习消息队列接口
  • 开发者不需要关心消息推送与接收
  • 开发者通过统一的API推送消息
  • 开发者的重点是实现业务逻辑功能



6. 怎么实现消息队列框架






  下面是作者开发的一个SOA框架,该框架提供了三种接口,分别是SOAP,RESTful,AMQP(RabbitMQ),理解了该框架思想,你很容易进一步扩展,例如增加XML-RPC, ZeroMQ等等支持。
  https://github.com/netkiller/SOA
  本文只讲消息队列框架部分。

6.1. 守护进程






  消息队列框架是本地应用程序(命令行程序),我们为了让他在后台运行,需要实现守护进程。
  https://github.com/netkiller/SOA/blob/master/bin/rabbitmq.php
  每个实例处理一组队列,实例化需要提供三个参数,$queueName = '队列名', $exchangeName = '交换名', $routeKey = '路由'

$daemon = new \framework\RabbitDaemon($queueName = 'email', $exchangeName = 'email', $routeKey = 'email');

  守护进程需要使用root用户运行,运行后会切换到普通用户,同事创建进程ID文件,一边进程停止的时候使用。
  守护进程核心代码https://github.com/netkiller/SOA/blob/master/system/rabbitdaemon.class.php

6.2. 消息队列协议






  消息协议是一个数组,将数组序列化或者转为JSON推送到消息队列服务器,这里使用json格式的协议。

$msg = array(
'Namespace'=>'namespace',
"Class"=>"Email",
"Method"=>"smtp",
"Param" => array(
$mail, $subject, $message, null
)
);

  序列化后的协议

{"Namespace":"single","Class":"Email","Method":"smtp","Param":["netkiller@msn.com","Hello"," TestHelloWorld",null]}

  使用json格式是考虑到通用性,这样推送端可以使用任何语言。如果不考虑兼容,建议使用二进制序列化,例如msgpack效率更好。

6.3. 消息队列处理






  消息队列处理核心代码
  https://github.com/netkiller/SOA/blob/master/system/rabbitmq.class.php
  所以消息的处理在下面一段代码中进行

$this->queue->consume(function($envelope, $queue) {
$speed = microtime(true);
$msg = $envelope->getBody();
$result = $this->loader($msg);
$queue->ack($envelope->getDeliveryTag()); //手动发送ACK应答
//$this->logging->info(''.$msg.' '.$result)
$this->logging->debug('Protocol: '.$msg.' ');
$this->logging->debug('Result: '. $result.' ');
$this->logging->debug('Time: '. (microtime(true) - $speed) .'');
});

  public function loader($msg = null) 负责拆解协议,然后载入对应的类文件,传递参数,运行方法,反馈结果。
  Time 可以输出程序运行所花费的时间,对于后期优化十分有用。

提示
  loader() 可以进一步优化,使用多线程每次调用loader将任务提交到线程池中,这样便可以多线程处理消息队列。



6.4. 测试






  测试代码 https://github.com/netkiller/SOA/blob/master/test/queue/email.php


<?php
$queueName = 'example';
$exchangeName = 'email';
$routeKey = 'email';
$mail = $argv[1];
$subject = $argv[2];
$message = empty($argv[3]) ? 'Hello World!' : ' '.$argv[3];

$connection = new AMQPConnection(array(
'host' => '192.168.4.1',
'port' => '5672',
'vhost' => '/',
'login' => 'guest',
'password' => 'guest'
));
$connection->connect() or die("Cannot connect to the broker!\n");
$channel = new AMQPChannel($connection);
$exchange = new AMQPExchange($channel);
$exchange->setName($exchangeName);
$queue = new AMQPQueue($channel);
$queue->setName($queueName);
$queue->setFlags(AMQP_DURABLE);
$queue->declareQueue();
$msg = array(
'Namespace'=>'namespace',
"Class"=>"Email",
"Method"=>"smtp",
"Param" => array(
$mail, $subject, $message, null
)
);
$exchange->publish(json_encode($msg), $routeKey);
printf("[x] Sent %s \r\n", json_encode($msg));

$connection->disconnect();

  这里只给出了少量测试与演示程序,如有疑问请到渎者群,或者公众号询问。

7. 总结






  该消息队列框架还比较简陋,但在生产环境已经运行很长一段时间,效果还是不错的。同时降低了消息队列的开发难度,开发者更多的时间是考虑业务逻辑的实现,而不用操心消息队列本身的使用。

8. 延伸阅读






  PHP高级编程之守护进程
  PHP高级编程之多线程

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-359020-1-1.html 上篇帖子: 安装PHP常见错误解决error 下篇帖子: PHP基础入门学习资料大全(共28个)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表