1、RabbitMQ 安装

RabbitMQ 的安装可以参考官方文档:https://www.rabbitmq.com/download.html

2、管理页面

rabbitmq-management插件提供基于HTTP的API方式管理和监控你的RabbitMQ服务器。

2.1、开启 rabbitmq_management 插件

  1. rabbitmq-plugins enable rabbitmq_management

windows 下运行如下命令

  1. rabbitmq-plugins.bat enable rabbitmq_management

2.2、登录管理页面

浏览器输入: http://localhost:15672 , 输入用户名和密码(默认为guest)。管理页面如下图:

3、php 安装 amqp 扩展

3.1、 下载对应的扩展

下载地址: https://pecl.php.net/package/amqp

假如需要安装 amqp-1.9.4

  1. wget http://pecl.php.net/get/amqp-1.9.4.tgz

3.2、安装

  1. tar -zxvf amqp-1.9..tgz
  2. cd cd amqp-1.9./
  3. ./configure --with-php-config=/path/to/php-config
  4. make && make install
  5. vim /path/to/php.ini
  6. extension=amqp.so

3.3、验证

  1. php -m | grep amqp

4、开发

项目采用 composer 管理依赖, 对应代码地址:https://github.com/SevenParadise/php-examples/tree/master/mq/rabbitmq/sample

4.1、安装php-amqplib依赖

  1. composer require php-amqplib/php-amqplib

4.2、生产者代码

  1. <?php
  2. require __DIR__ . '/../../../vendor/autoload.php';
  3.  
  4. use PhpAmqpLib\Message\AMQPMessage;
  5. use PhpAmqpLib\Exchange\AMQPExchangeType;
  6. use PhpAmqpLib\Connection\AMQPStreamConnection;
  7.  
  8. // todo 换成自己的配置
  9. $host = '192.168.33.1';
  10. $port = 5672;
  11. $username = 'zhangcs';
  12. $password = 'zhangcs';
  13. $vhost = '/';
  14.  
  15. // 1、连接到 RabbitMQ Broker,建立一个连接
  16. $connection = new AMQPStreamConnection($host, $port, $username, $password, $vhost);
  17.  
  18. // 2、开启一个通道
  19. $channel = $connection->channel();
  20.  
  21. $exchange = 'test_exchange';
  22. $queue = 'test_queue';
  23. // 3、声明一个交换器,并且设置相关属性
  24. $channel->exchange_declare($exchange, AMQPExchangeType::DIRECT, false, true, false);
  25.  
  26. // 4、声明一个队列, 并且设置相关属性
  27. $channel->queue_declare($queue, false, true, false, false);
  28.  
  29. // 5、通过路由键将交换器和队列绑定起来
  30. $channel->queue_bind($queue, $exchange);
  31.  
  32. $body = $argv[1] ?? 'Hello RabbitMQ';
  33.  
  34. // 6、初始化消息,并且持久化消息
  35. $message = new AMQPMessage($body, [
  36. 'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT
  37. ]);
  38.  
  39. // 7、将消息发送到 RabbitMQ Broker
  40. $channel->basic_publish($message, $exchange);
  41.  
  42. // 8、关闭通道
  43. $channel->close();
  44. // 9、关闭连接
  45. $connection->close();

4.3、消费者代码

  1. <?php
  2. require __DIR__ . '/../../../vendor/autoload.php';
  3.  
  4. use PhpAmqpLib\Exchange\AMQPExchangeType;
  5. use PhpAmqpLib\Connection\AMQPStreamConnection;
  6.  
  7. // todo 换成自己的配置
  8. $host = '192.168.33.1';
  9. $port = 5672;
  10. $username = 'zhangcs';
  11. $password = 'zhangcs';
  12. $vhost = '/';
  13.  
  14. // 1、连接到 RabbitMQ Broker,建立一个连接
  15. $connection = new AMQPStreamConnection($host, $port, $username, $password, $vhost);
  16.  
  17. // 2、开启一个通道
  18. $channel = $connection->channel();
  19.  
  20. $exchange = 'test_exchange';
  21. $queue = 'test_queue';
  22.  
  23. // 3、声明一个交换器,并且设置相关属性
  24. $channel->exchange_declare($exchange, AMQPExchangeType::DIRECT, false, true, false);
  25.  
  26. // 4、声明一个队列, 并且设置相关属性
  27. $channel->queue_declare($queue, false, true, false, false);
  28.  
  29. // 5、通过路由键将交换器和队列绑定起来
  30. $channel->queue_bind($queue, $exchange);
  31.  
  32. function process_message($message)
  33. {
  34. echo "\n--------\n";
  35. echo $message->body;
  36. echo "\n--------\n";
  37.  
  38. $message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']);
  39. // Send a message with the string "quit" to cancel the consumer.
  40. if ($message->body === 'quit') {
  41. $message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']);
  42. }
  43. }
  44.  
  45. // 6、消费消息,并且设置回调函数为 process_message
  46. $channel->basic_consume($queue, 'hahah', false, false, false, false, 'process_message');
  47.  
  48. // 7、注册终止函数,关闭通道,关闭连接
  49. function shutdown($channel, $connection)
  50. {
  51. $channel->close();
  52. $connection->close();
  53. }
  54. register_shutdown_function('shutdown', $channel, $connection);
  55.  
  56. // 8、一直阻塞消费数据
  57. while ($channel ->is_consuming()) {
  58. $channel->wait();
  59. }

4.4、运行

运行消费者

  1. $ php mq/rabbitmq/sample/consumer.php

运行生产者

  1. $ php mq/rabbitmq/sample/producer.php 'message'
  2. # 关闭消费者
  3. $ php mq/rabbitmq/sample/producer.php 'quit'

消费结果如下:

5、方法详解

5.1、exchange_declare 方法

声明交换器方法,函数声明如下

  1. public function exchange_declare(
  2. $exchange,
  3. $type,
  4. $passive = false,
  5. $durable = false,
  6. $auto_delete = true,
  7. $internal = false,
  8. $nowait = false,
  9. $arguments = array(),
  10. $ticket = null
  11. )
  • $exchange: 交换器名称
  • $type: 交换器类型,常见的如 fanout、direct、topic,详情见:【RabbitMQ 实战指南】一 RabbitMQ入门
  • $passive: 判断交换器是否存在,当设置为true是,然后交换器不存在时,会抛出异常
  • $durable: 设置是否持久化。durable 设置为true表示持久化。持久化可以将交换器存盘,在服务器重启的时候不会丢失相关消息。
  • $auto_delete: 设置是否自动删除,auto_delete 设置为 true 则表示自动删除。自动 删除的前提是至少有一个队列或者交换器与这个交换器绑定 ,之后所有与这个交换器绑 定的队列或者交换器都与 此解绑。注意不能错误地把这个参数理解为 : "当与此交换器 连接的客户端都断开时 , RabbitMQ 会自动 删 除本交换器 "。
  • $internal: 设置是否是内置的。如果设置为 true,则表示是内置的交换器,客户端程 序无法直接发送消息到这个交换器中,只能通过交换器路由到交换器这种方式。
  • $nowait: 设置是否需要等待服务器返回回执消息,默认为false

5.2、queue_declare 方法

声明队列方法,函数声明如下

  1. public function queue_declare(
  2. $queue = '',
  3. $passive = false,
  4. $durable = false,
  5. $exclusive = false,
  6. $auto_delete = true,
  7. $nowait = false,
  8. $arguments = array(),
  9. $ticket = null
  10. )
  • $queue: 队列名称
  • $passive: 判断队列是否存在,当设置为true是,然后队列不存在时,会抛出异常
  • $durable: 设置是否持久化。durable 设置为true表示持久化。持久化可以将队列存盘,在服务器重启的时候不会丢失相关消息。
  • $exclusive: 设置为排他。为 true 则设置队列为排他的。如果一个队列被声明为排他队列,该队列仅对首次声明它的连接可见,并在连接断开时自动删除。这里需要注意三点:排他队列是基于连接(Connection)可见的,同一个连接的不同信道(Channel)是可以同时访问统一连接创建的排他队列;"首次" 是指如果一个连接已经声明了一个排他队列,其他连接是不允许建立同名的排他队列的,这个与普通队列不同,即使该队列是持久化的,一旦连接关闭或者客户端退出,该排他队列都会被自动删除,这种队列适用与一个客户端同时发送和读取消息的应用场景。
  • $auto_delete: 设置是否自动删除。为true则设置队列为自动删除。自动删除的前提是: 至少有一个消费者连接到这个队列,之后所有与这个队列连接的消费者都断开时,才会 自动删除。不能把这个参数错误地理解为: "当连接到此队列的所有客户端断开时,这 个队列自动删除",因为生产者客户端创建这个队列,或者没有消费者客户端与这个队 列连接时,都不会自动删除这个队列。
  • $nowait: 设置是否需要等待服务器返回回执消息,默认为false

5.3、queue_bind 方法

绑定队列和交换器方法,函数声明如下

  1. public function queue_bind(
  2. $queue,
  3. $exchange,
  4. $routing_key = '',
  5. $nowait = false,
  6. $arguments = array(),
  7. $ticket = null
  8. )
  • $queue: 队列名称
  • $exchange: 交换器名称
  • $routing_key : 用来绑定队列和交换器的路由键
  • $nowait: 设置是否需要等待服务器返回回执消息,默认为false

5.4、exchange_bind 方法

我们不仅可以将队列和交换器绑定,也可以将交换器和交换器绑定,函数声明如下

  1. public function exchange_bind(
  2. $destination,
  3. $source,
  4. $routing_key = '',
  5. $nowait = false,
  6. $arguments = array(),
  7. $ticket = null
  8. )
  • $destination: 目标交换器名称
  • $source: 源交换器名称
  • $routing_key : 用来源交换器和目标交换器的路由键
  • $nowait: 设置是否需要等待服务器返回回执消息,默认为false

生产者发送消息至交换器 source 中, 交换器 source 根据路由键找到与其匹配的另一个交换器 destination, 并把消息转发到 destination 中,进而存储在 destination 绑定的 queue 中,如下图:

5.5、basic_publish

发送消息方法,函数声明如下

  1. public function basic_publish(
  2. $msg,
  3. $exchange = '',
  4. $routing_key = '',
  5. $mandatory = false,
  6. $immediate = false,
  7. $ticket = null
  8. )
  • $msg: 需要发送的消息,PhpAmqpLib\Message\AMQPMessage 对象,可以设置特定属性,比如消息是否持久化,消息的优先级
  • $exchange: 交换器的名称,指明消息需要发送到哪个交换器中,如果设置为空字符串,会发送给 RabbitMQ 默认的交换器 " AMQP default " 中
  • $routing_key: 路由键
  • $mandatory: 当 mandatory 设置为true 时,交换器无法通过自身的类型和路由键找到一个符合条件的队列,那么 RabbitMQ 会调用 Basic.Return 命令将消息返回给生产者 。当 mandatory 参 数设置为 false 时,出现上述情形,则消息直接被丢弃 。 生产者可以通过添加一个监听器监听消息是否正确路由到队列中
  • $immediate: 当 imrnediate 参数设为 true 时,如果交换器在将消息路由到队列时发现队列上并不存在 任何消费者,那么这条消息将不会存入队列中。当与路由键匹配 的所有队列都没有消费者时 , 该消息会至生产者。

5.6、basic_consume

消费消息方法,函数声明如下

  1. public function basic_consume(
  2. $queue = '',
  3. $consumer_tag = '',
  4. $no_local = false,
  5. $no_ack = false,
  6. $exclusive = false,
  7. $nowait = false,
  8. $callback = null,
  9. $ticket = null,
  10. $arguments = array()
  11. )
  • $queue: 队列名称
  • $consumer_tag: 消费者标签,用来区分多个消费者
  • $no_local: 设置为 true 则表示不能将同一个 Connection 中生产者发送的消息传送给这个 Connection 中的消费者
  • $no_ack: 设置为自动确认,详细可参考连接: RabbitMQ 之 no_ack 分析
  • $exclusive: 是否设置为排他
  • $callback: 设置消费者的回调函数。用于处理 RabbitMQ 推送过来的消息

【RabbitMQ 实战指南】一 RabbitMQ 开发的更多相关文章

  1. 【RabbitMQ 实战指南】一 延迟队列

    1.什么是延迟队列 延迟队列中存储延迟消息,延迟消息是指当消息被发送到队列中不会立即消费,而是等待一段时间后再消费该消息. 延迟队列很多应用场景,一个典型的应用场景是订单未支付超时取消,用户下单之后3 ...

  2. .Net RabbitMQ实战指南——RabbitMQ相关概念介绍

    什么是消息中间件 消息(Message)是指在应用间传送的数据.消息可以非常简单,比如只包含文本字符串.JSON等,也可以很复杂,比如内嵌对象. 消息队列中间件(Message Queue Middl ...

  3. 【RabbitMQ 实战指南】一 RabbitMQ入门

    1.消息中间件 1.1.什么是消息中间件 消息中间件(Message Queue Middleware,简称 MQ)是指利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通道来进行分布式系 ...

  4. .Net RabbitMQ实战指南——服务日志

    RabbitMQ的日出输入方式有很多种:file.console .syslog .exchange. 在RabbitMQ中,日志级别有none(0).critical(4).error(8).war ...

  5. .Net RabbitMQ实战指南——客户端开发

    开发中关键的Class和Interface有Channel.Connection.ConnectionFactory.Consumer等,与RabbitMQ相关的开发工作,基本上是围绕Connecti ...

  6. 【RabbitMQ 实战指南】一 死信队列

    1.死信队列 DLX,全称为 Dead-Letter-Exchange,可以称之为死信交换器.当消息在一个队列中变成死信(dead message)之后,它能被发送到另一个交换器中,这个交换器就是DL ...

  7. 【RabbitMQ 实战指南】一 过期时间TTL

    RabbitMQ 可以对消息和队列设置过期时间(TTL) 1.设置消息的TTL 目前有两种方式可以设置消息的TTL 第一种方式是通过队列属性设置,队列中所有消息都有相同的过期时间 第二种方式是对消息本 ...

  8. .Net RabbitMQ实战指南——进阶(一)

    备份交换器 备份交换器,英文名称为Alternate Exchange,简称AE.通过在声明交换器(调用channel.ExchangeDeclare方法)时添加alternate-exchange参 ...

  9. .Net RabbitMQ实战指南——进阶(二)

    持久化 持久化可以提高RabbitMQ的可靠性,防止异常情况下的数据丢失.RabbitMQ的持久化分为三个部分:交换器的持久化.队列的持久化和消息的持久化. 交换器的持久化通过声明队列时将durabl ...

随机推荐

  1. Java第三次作业第一题

    1.[请复制本程序,作为java程序代码,进行编译,补充填写缺失代码部分,并实现题目要求功能,从而获得空白填写所需的内容.] 编写无限计时程序,从0:1开始计时,一直循环计时,计时到60秒,变为1:0 ...

  2. log4j日志不输出的问题

    今天服务器上报错,想先去看一下日志进行排查,结果发现日志很久都没有输出过了.从上午排查到下午,刚刚解决,因此记录一下,但现在也只是知其然,并不知其所以然,所以如果大家有什么想法请在下方评论. 先说一下 ...

  3. Ubuntu+docker+jenkins安装详细指南

    最近项目上开始实行自动化测试,避免不了与jenkins等持续集成工具打交道,今天就给大家分享一下有关jenkins的简单安装和使用 1,准备环境 (1)ubuntu系统 (2)docker (3)je ...

  4. Python学习-列表深浅拷贝

    一.先看一个简单的赋值语句 lst1 = ['France', 'Belgium', 'England'] lst2 = lst1 # lst1.append('Uruguay') lst2.appe ...

  5. Linux-----centos6.2---安装Linux的流程

      1.安装命令 # yum install mysql-server mysql 2.查看是否安装正确 # chkconfig --list mysqld 3.启动 (1).启动服务: # serv ...

  6. Spring boot 官网学习笔记 - Using Spring Boot without the Parent POM,但是还要使用Parent POM提供的便利

    If you do not want to use the spring-boot-starter-parent, you can still keep the benefit of the depe ...

  7. Spring 梳理-容器(container)

    虽然Spring的组件代码是轻量级的,但它的配置却是重量级的.一开始,Spring用XML配置,而且是很多XML配置.Spring 2.5引入了基于注解的组件扫描,这消除了大量针对应用程序自身组件的显 ...

  8. opencv之霍夫曼变换

    霍夫变换不仅可以找出图片中的直线,也可以找出圆,椭圆,三角形等等,只要你能定义出直线方程,圆形的方程等等. 不得不说,现在网上的各种博客质量真的不行,网上一堆文章,乱TM瞎写,误人子弟.本身自己就没有 ...

  9. SUSE Storage6 环境搭建详细步骤 - Win10 + VMware WorkStation

    学习 SUSE Storage 系列文章 (1)SUSE Storage6 实验环境搭建详细步骤 - Win10 + VMware WorkStation (2)SUSE Linux Enterpri ...

  10. 自定义属性--JavaScript

    1 - 获取属性值 element.属性 获取属性值 element.getAttribute('属性') 区别: element.属性 --获取内置属性(元素本身自带的属性) element.get ...