上一篇记录下RabbitMQ的安装与管理界面,接下来开始看PHP是如何接入的

1.安装php-amqplib

php-amqplib是一个纯PHP库,使用它,基于PHP的脚本客户端就可以轻松的连接和操作RabbitMQ。我们使用composer来安装。

composer require php-amqplib/php-amqplib

示例说明

生产者(Producer)和消费者(Consumer)是消息队列的基本概念,生产者是指生产消息的一方,也是消息发送方,消费者就是消费消息的一方,也是消息接收方,队列就是存储消息的一个缓存区。

本实例将由生产者发送很多消息给消息队列,由多个消费者来消费队列中的消息。我们可以想象这样的场景:皮鞋生产打包打包车间,不断有成品鞋进入传送带(消息队列)等待操作工人(消费者)将皮鞋打包。

因为等待打包的鞋子特别多,我们需要安排多个打包工人在传送带两边,及时从传送带取出成品鞋,然后装箱打包。我们要求是要确保工人最后打包好的皮鞋数量一双不少,不能因为打包工人操作慢或者个人原因暂时离开生产线,导致最终打包数不一致。

消息发送

生产者将消息发送给队列,至于谁来消费(处理)这些消息,生产者不管。

消息队列(MQ),用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。

消息到达队列中后,如果没有一个消费者来处理消息的话,我们希望队列中的消息不要丢弃,也就是消息持久化。在生产者和消费者中都要将queue_declare第3个参数设置为true,表示让消息队列持久化。

$channel->queue_declare($queue, false, true, false, false); 

此外,我们可以确保即使RabbitMQ重启了,消息队列不会丢失,在生产者端设置:。

'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT

生产者文件sender.php

<?php
/**
* @sender.php
* @消息生产者-分发任务
*/ require_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage; $queue = 'worker'; //$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$connection = new AMQPStreamConnection(
'192.168.0.100',
56720,
'helloweba', //user
'helloweba', //password
'test' //vhost
);
$channel = $connection->channel(); $channel->queue_declare($queue, false, true, false, false); //第3个参数设置为true,表示让消息队列持久化 for ($i = 0; $i < 100; $i++) {
$arr = [
'id' => 'message_' . $i,
'order_id' => str_replace('.', '' , microtime(true)) . mt_rand(10, 99) . $i,
'content' => 'helloweba-' . time()
];
$data = json_encode($arr);
$msg = new AMQPMessage($data, ['delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT]); ////设置rabbitmq重启后也不会丢失队列,或者设置为'delivery_mode' => 2
$channel->basic_publish($msg, '', $queue); echo 'Send message: ' . $data . PHP_EOL;
} $channel->close();
$connection->close();

消息接收

消费者是指完成消息的接收和处理的客户端程序,消费者就如同生产线上的操作工人,他们按照操作规程从传送带上取出产品后有序的完成后续工作任务。

实际项目中,如果消费者处理消息能力不够时,就要开启多个消费者来消费队列中的消息。默认情况下,RabbitMQ将会把队列中的消息平均分配给每个消费者。如果消费者要对分配到的消息任务处理时间很长(耗时任务),那么处理消息任务的时候就有可能会遇到意外。

比如某个消费者断电了,或者出故障了,那它正在处理的消息会怎么办?这里就是RabbitMQ的消息确认机制,为了保证数据不丢失,RabbitMQ会将未处理完的消息分配给下一个消费者处理。

此外RabbitMQ还可以设置公平分配消息任务,不会给某个消费者同时分配多个消息处理任务,因为消费者无法同时处理多个消息任务。

换句话说,RabbitMQ在处理和确认消息之前,不会向消费者发送新的消息,而是将消息分发给下一个不忙的消费者。

$channel->basic_qos(null, 1, null); //处理和确认完消息后再消费新的消息

消费者文件receiver.php

<?php
/**
* @receiver.php
* @消息消费者-接收端
*/ require_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection; $queue = 'worker'; //$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$connection = new AMQPStreamConnection('192.168.0.100', 56720, 'helloweba', 'helloweba', 'test');
$channel = $connection->channel(); $channel->queue_declare($queue, false, true, false, false); echo ' [*] Waiting for messages. To exit press CTRL+C' . PHP_EOL; $callback = function($msg){
echo " Received message:", $msg->body, PHP_EOL;
sleep(1); //模拟耗时执行
$msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
}; $channel->basic_qos(null, 1, null); //处理和确认完消息后再消费新的消息
$channel->basic_consume($queue, '', false, false, false, false, $callback); //第4个参数值为false表示启用消息确认 while(count($channel->callbacks)) {
$channel->wait();
} $channel->close();
$connection->close();

模拟测试

现在我们运行多个消费者终端,可以打开多个ssh客户端,client1和client2运行:

php receiver.php

开启生产者
php sender.php

由于消费者是阻塞运行的,他们会一直等待队列中的消息,当有消息就会去取出来处理。我们可以模拟将其中某个客户端中断,即断开某个消费者。

然后再看消息是不是被其他消费者接收处理了。同样我们可以模拟将客户端全部重启,看看队列中的消息是否没有丢失。

当client1中断连接RabbitMQ后,再次运行连接RabbitMQ,在client2中看到的消息处理情况,注意看图中的消息id。

RabbitMQ接入之PHP的更多相关文章

  1. Springboot接入RabbitMQ详细教程

    本文适用于对 RabbitMQ 有所了解的人,在此不讨论MQ的原理,只讨论如何接入.其实Spring Boot 集成 RabbitMQ 非常简单,本文章使用的是Spring Boot 提供了sprin ...

  2. Spring MVC 接入 rabbitMQ

    依赖包 <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spr ...

  3. Day11-协程/异步IO/RabbitMQ

    协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候 ...

  4. 网易蜂巢微服务架构:用RabbitMQ实现轻量级通信

    本次分享内容由三个部分组成: 微服务架构与MQ RabbitMQ场景分析与优化 RabbitMQ在网易蜂巢中的应用和案例分享 1微服务架构与MQ 微服务架构是一种架构模式,它将单体应用划分成一组微小的 ...

  5. python学习道路(day11note)(协程,同步与异步的性能区别,url爬网页,select,RabbitMq)

    1.协程 #协程 又称微线程 是一种用户的轻量级线程 程序级别代码控制 就不用加机器 #不同函数 = 不同任务 A函数切到B函数没有进行cpu级别的切换,而是程序级别的切换就是协程 yelied #单 ...

  6. RabbitMQ介绍1 - 由来

    RabbitMQ是一个异步消息通信中间件,用erlang语言开发,实现了AMQP(Advanced Message Queue )协议,是一个开源产品,官方网站:http://www.rabbitmq ...

  7. Day10 - Python协程、异步IO、redis缓存、rabbitMQ队列

    Python之路,Day9 - 异步IO\数据库\队列\缓存   本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitM ...

  8. Python之异步IO&RabbitMQ&Redis

    协程: 1.单线程运行,无法实现多线程. 2.修改数据时不需要加锁(单线程运行),子程序切换是线程内部的切换,耗时少. 3.一个cpu可支持上万协程,适合高并发处理. 4.无法利用多核资源,因为协程只 ...

  9. RabbitMQ死信队列另类用法之复合死信

    前言 在业务开发过程中,我们常常需要做一些定时任务,这些任务一般用来做监控或者清理任务,比如在订单的业务场景中,用户在创建订单后一段时间内,没有完成支付,系统将自动取消该订单,并将库存返回到商品中,又 ...

  10. RabbitMQ集群搭建和使用

    一.环境准备 1.选择RabbitMQ的版本 http://www.rabbitmq.com/changelog.html 注: 不同版本的Linux选择的RabbitMQ版本也不同,参照 http: ...

随机推荐

  1. mysql事务隔离级别及MVCC 原理

    一.事务的隔离级别 为了保证事务与事务之间的修改操作不会互相影响,innodb希望不同的事务是隔离的执行的,互不干扰. 两个并发的事务在执行过程中有 读读.读写(一个事务在读某条数据的同时另一个事务在 ...

  2. Python将表格文件中某些列的数据整体向上移动一行

      本文介绍基于Python语言,针对一个文件夹下大量的Excel表格文件,对其中的每一个文件加以操作--将其中指定的若干列的数据部分都向上移动一行,并将所有操作完毕的Excel表格文件中的数据加以合 ...

  3. 数据结构 - 关键路径(AOE)

    数据结构 - 关键路径求解

  4. Python计算傅里叶变换

    技术背景 傅里叶变换在几乎所有计算相关领域都有可能被使用到,例如通信领域的滤波.材料领域的晶格倒易空间计算还有分子动力学中的倒易力场能量项等等.最简单的例子来说,计算周期性盒子的电势能\(k\sum_ ...

  5. Rust字符串类型全解析

    字符串是每种编程语言都绕不开的类型, 不过,在Rust中,你会看到远比其他语言更加丰富多样的字符串类型. 如下图: 为什么Rust中需要这么多种表示字符串的类型呢? 初学Rust时,可能无法理解为什么 ...

  6. `->` 操作符重载的注意事项

    在 C++ 中,-> 操作符可以被重载,用于对象的指针成员访问. 重载后的 -> 操作符主要用于模拟指针访问行为,常见于智能指针的实现等复杂场景. -> 操作符重载后的调用触发流程: ...

  7. C#/.NET/.NET Core优秀项目和框架2024年9月简报

    前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍.功能特点.使用方式以及部分功能截图 ...

  8. 64.element表单校验注意点

    <!-- 表单验证三要素: --> <!-- ① el-form需要有 model属性[表单数据对象].rules属性[验证规则对象].ref属性[引用字符串] --> < ...

  9. 使用Spectre.Console定制.NET控制台输出样式演示

      创建一个控制台项目,引用包Spectre.Console.或者如果需要定制控制台cli命令,也可以引用 Spectre.Console.Cli ,里面自带包含了Spectre.Console   ...

  10. 探索 PCI 转 PMC 载板转接卡:连接不同接口的桥梁

    探索 PCI 转 PMC 载板转接卡:连接不同接口的桥梁 在计算机硬件领域,各种接口和总线标准不断演进,以满足日益增长的性能和功能需求.在这个过程中,不同接口之间的转换设备应运而生,其中 PCI 转 ...