PHP+RabbitMQ实现消息队列的完整代码


Posted in PHP onMarch 20, 2019

前言

为什么使用RabbitMq而不是ActiveMq或者RocketMq?

首先,从业务上来讲,我并不要求消息的100%接受率,并且,我需要结合php开发,RabbitMq相较RocketMq,延迟较低(微妙级)。至于ActiveMq,貌似问题较多。RabbitMq对各种语言的支持较好,所以选择RabbitMq。

先安装PHP对应的RabbitMQ,这里用的是 php_amqp 不同的扩展实现方式会有细微的差异.

php扩展地址: http://pecl.php.net/package/amqp

具体以官网为准  http://www.rabbitmq.com/getstarted.html

介绍

  • config.php 配置信息
  • BaseMQ.php MQ基类
  • ProductMQ.php 生产者类
  • ConsumerMQ.php 消费者类
  • Consumer2MQ.php 消费者2(可有多个)

config.php

<?php
 return [
  //配置
  'host' => [
   'host' => '127.0.0.1',
   'port' => '5672',
   'login' => 'guest',
   'password' => 'guest',
   'vhost'=>'/',
  ],
  //交换机
  'exchange'=>'word',
  //路由
  'routes' => [],
 ];

BaseMQ.php

<?php
 /**
  * Created by PhpStorm.
  * User: pc
  * Date: 2018/12/13
  * Time: 14:11
  */
 
 namespace MyObjSummary\rabbitMQ;
 
 /** Member
  *  AMQPChannel
  *  AMQPConnection
  *  AMQPEnvelope
  *  AMQPExchange
  *  AMQPQueue
  * Class BaseMQ
  * @package MyObjSummary\rabbitMQ
  */
 class BaseMQ
 {
  /** MQ Channel
   * @var \AMQPChannel
   */
  public $AMQPChannel ;
 
  /** MQ Link
   * @var \AMQPConnection
   */
  public $AMQPConnection ;
 
  /** MQ Envelope
   * @var \AMQPEnvelope
   */
  public $AMQPEnvelope ;
 
  /** MQ Exchange
   * @var \AMQPExchange
   */
  public $AMQPExchange ;
 
  /** MQ Queue
   * @var \AMQPQueue
   */
  public $AMQPQueue ;
 
  /** conf
   * @var
   */
  public $conf ;
 
  /** exchange
   * @var
   */
  public $exchange ;
 
  /** link
   * BaseMQ constructor.
   * @throws \AMQPConnectionException
   */
  public function __construct()
  {
   $conf = require 'config.php' ;
   if(!$conf)
    throw new \AMQPConnectionException('config error!');
   $this->conf  = $conf['host'] ;
   $this->exchange = $conf['exchange'] ;
   $this->AMQPConnection = new \AMQPConnection($this->conf);
   if (!$this->AMQPConnection->connect())
    throw new \AMQPConnectionException("Cannot connect to the broker!\n");
  }
 
  /**
   * close link
   */
  public function close()
  {
   $this->AMQPConnection->disconnect();
  }
 
  /** Channel
   * @return \AMQPChannel
   * @throws \AMQPConnectionException
   */
  public function channel()
  {
   if(!$this->AMQPChannel) {
    $this->AMQPChannel = new \AMQPChannel($this->AMQPConnection);
   }
   return $this->AMQPChannel;
  }
 
  /** Exchange
   * @return \AMQPExchange
   * @throws \AMQPConnectionException
   * @throws \AMQPExchangeException
   */
  public function exchange()
  {
   if(!$this->AMQPExchange) {
    $this->AMQPExchange = new \AMQPExchange($this->channel());
    $this->AMQPExchange->setName($this->exchange);
   }
   return $this->AMQPExchange ;
  }
 
  /** queue
   * @return \AMQPQueue
   * @throws \AMQPConnectionException
   * @throws \AMQPQueueException
   */
  public function queue()
  {
   if(!$this->AMQPQueue) {
    $this->AMQPQueue = new \AMQPQueue($this->channel());
   }
   return $this->AMQPQueue ;
  }
 
  /** Envelope
   * @return \AMQPEnvelope
   */
  public function envelope()
  {
   if(!$this->AMQPEnvelope) {
    $this->AMQPEnvelope = new \AMQPEnvelope();
   }
   return $this->AMQPEnvelope;
  }
 }

ProductMQ.php

<?php
 //生产者 P
 namespace MyObjSummary\rabbitMQ;
 require 'BaseMQ.php';
 class ProductMQ extends BaseMQ
 {
  private $routes = ['hello','word']; //路由key
 
  /**
   * ProductMQ constructor.
   * @throws \AMQPConnectionException
   */
  public function __construct()
  {
   parent::__construct();
  }
 
  /** 只控制发送成功 不接受消费者是否收到
   * @throws \AMQPChannelException
   * @throws \AMQPConnectionException
   * @throws \AMQPExchangeException
   */
  public function run()
  {
   //频道
   $channel = $this->channel();
   //创建交换机对象
   $ex = $this->exchange();
   //消息内容
   $message = 'product message '.rand(1,99999);
   //开始事务
   $channel->startTransaction();
   $sendEd = true ;
   foreach ($this->routes as $route) {
    $sendEd = $ex->publish($message, $route) ;
    echo "Send Message:".$sendEd."\n";
   }
   if(!$sendEd) {
    $channel->rollbackTransaction();
   }
   $channel->commitTransaction(); //提交事务
   $this->close();
   die ;
  }
 }
 try{
  (new ProductMQ())->run();
 }catch (\Exception $exception){
  var_dump($exception->getMessage()) ;
 }

ConsumerMQ.php

<?php
 //消费者 C
 namespace MyObjSummary\rabbitMQ;
 require 'BaseMQ.php';
 class ConsumerMQ extends BaseMQ
 {
  private $q_name = 'hello'; //队列名
  private $route = 'hello'; //路由key
 
  /**
   * ConsumerMQ constructor.
   * @throws \AMQPConnectionException
   */
  public function __construct()
  {
   parent::__construct();
  }
 
  /** 接受消息 如果终止 重连时会有消息
   * @throws \AMQPChannelException
   * @throws \AMQPConnectionException
   * @throws \AMQPExchangeException
   * @throws \AMQPQueueException
   */
  public function run()
  {
 
   //创建交换机
   $ex = $this->exchange();
   $ex->setType(AMQP_EX_TYPE_DIRECT); //direct类型
   $ex->setFlags(AMQP_DURABLE); //持久化
   //echo "Exchange Status:".$ex->declare()."\n";
 
   //创建队列
   $q = $this->queue();
   //var_dump($q->declare());exit();
   $q->setName($this->q_name);
   $q->setFlags(AMQP_DURABLE); //持久化
   //echo "Message Total:".$q->declareQueue()."\n";
 
   //绑定交换机与队列,并指定路由键
   echo 'Queue Bind: '.$q->bind($this->exchange, $this->route)."\n";
 
   //阻塞模式接收消息
   echo "Message:\n";
   while(True){
    $q->consume(function ($envelope,$queue){
     $msg = $envelope->getBody();
     echo $msg."\n"; //处理消息
     $queue->ack($envelope->getDeliveryTag()); //手动发送ACK应答
    });
    //$q->consume('processMessage', AMQP_AUTOACK); //自动ACK应答
   }
   $this->close();
  }
 }
 try{
  (new ConsumerMQ)->run();
 }catch (\Exception $exception){
  var_dump($exception->getMessage()) ;
 }

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
PHP如何编写易读的代码
Jul 10 PHP
PHP5+UTF8多文件上传类
Oct 17 PHP
基于PHP文件操作的详解
Jun 05 PHP
PHP代码审核的详细介绍
Jun 13 PHP
Codeigniter操作数据库表的优化写法总结
Jun 12 PHP
一个不易被发现的PHP后门代码解析
Jul 05 PHP
8个PHP程序员常用的功能汇总
Dec 18 PHP
php基于curl扩展制作跨平台的restfule 接口
May 11 PHP
PHP实现的迪科斯彻(Dijkstra)最短路径算法实例
Sep 16 PHP
PHP实现的XXTEA加密解密算法示例
Aug 28 PHP
PHP单例模式实例分析【防继承,防克隆操作】
May 22 PHP
Laravel实现批量更新多条数据
Apr 06 PHP
PHP实现的数据对象映射模式详解
Mar 20 #PHP
PHP单例模式数据库连接类与页面静态化实现方法
Mar 20 #PHP
PHP实现的策略模式示例
Mar 20 #PHP
PHP实现数组和对象的相互转换操作示例
Mar 20 #PHP
Laravel5.4框架使用socialite实现github登录的方法
Mar 20 #PHP
PHP工厂模式的日常使用
Mar 20 #PHP
PHP函数积累总结
Mar 19 #PHP
You might like
PHP中实现中文字符进制转换原理分析
2011/12/06 PHP
PHP版微信公众平台红包API
2015/04/02 PHP
php开发最强大的IDE编辑的phpstorm 2020.2配置Xdebug调试的详细教程
2020/08/17 PHP
克隆javascript对象的三个方法小结
2011/01/12 Javascript
jQuery Ajax 实例全解析
2011/04/20 Javascript
自定义ExtJS控件之下拉树和下拉表格附源码
2013/10/15 Javascript
使用js显示当前时间示例
2014/03/02 Javascript
from表单多个按钮提交用onclick跳转不同action
2014/04/24 Javascript
javascript动态设置样式style实例分析
2015/05/13 Javascript
在JavaScript中使用JSON数据
2016/02/15 Javascript
JavaScript中windows.open()、windows.close()方法详解
2016/07/28 Javascript
JavaScript中数组Array.sort()排序方法详解
2017/03/01 Javascript
常用的js方法合集
2017/03/10 Javascript
JavaScript注册时密码强度校验代码
2017/06/30 Javascript
react 应用多入口配置及实践总结
2018/10/17 Javascript
详解vue项目打包步骤
2019/03/29 Javascript
js尾调用优化的实现
2019/05/23 Javascript
pageGroup.js实现分页功能
2019/07/27 Javascript
vue点击页面空白处实现保存功能
2019/11/06 Javascript
python简单获取数组元素个数的方法
2015/07/13 Python
基于Python os模块常用命令介绍
2017/11/03 Python
django admin 后台实现三级联动的示例代码
2018/06/22 Python
PyQt5笔记之弹出窗口大全
2019/06/20 Python
Django 使用easy_thumbnails压缩上传的图片方法
2019/07/26 Python
pandas 对日期类型数据的处理方法详解
2019/08/08 Python
基于Python3.6中的OpenCV实现图片色彩空间的转换
2020/02/03 Python
Python实现计算图像RGB均值方式
2020/06/04 Python
python爬取”顶点小说网“《纯阳剑尊》的示例代码
2020/10/16 Python
HTML5触摸事件(touchstart、touchmove和touchend)的实现
2020/05/08 HTML / CSS
美国学校校服,儿童和婴儿服装:Cookie’s Kids
2016/10/14 全球购物
介绍一下SQL中union,intersect和minus
2012/04/05 面试题
教育基金募捐倡议书
2014/05/14 职场文书
常务副县长“四风”个人对照检查材料思想汇报
2014/10/02 职场文书
迁户口计划生育证明
2014/10/19 职场文书
关于车尾的标语大全
2015/08/11 职场文书
MySQL如何解决幻读问题
2021/08/07 MySQL