hyperf 如何对AMQP消息进行手动消费?
转发自白狼栈:查看原文
在使用 hyperf 官方自带的 AMQP 队列时你会发现,不需要我们再额外启动进程对消息进行消费。这是因为默认情况下,使用 @Consumer 注解时,hyperf 会为我们自动创建子进程启动消费者,并且会在子进程异常退出后,重新拉起。
来看一个简单的例子。
1、创建producer
php bin/hyperf.php gen:amqp-producer DemoProducer
2、投递消息
namespace App\Controller;
use App\Amqp\Producer\DemoProducer;
use Hyperf\Amqp\Producer;
use Hyperf\Utils\ApplicationContext;
class IndexController extends AbstractController
{
public function index()
{
$user = $this->request->input('user', 'Hyperf');
$data = [
'message' => "Hello {$user}.",
];
$message = new DemoProducer($data);
$producer = ApplicationContext::getContainer()->get(Producer::class);
$producer->produce($message);
return 'ok';
}
}
3、创建消费者
php bin/hyperf.php gen:amqp-consumer DemoConsumer
4、测试
启动项目,浏览器访问 http://127.0.0.1:9501/ ,我们可以在控制台看到打印的消息输出。
Array
(
[method] => GET
[message] => Hello Hyperf.
)
[DEBUG] 1 acked.
这个是 hyperf 自启动进程对消息进行消费。
现在我们想把消费进程从项目中剥离出来,用其他机器单独进行消费。
我们参考 hyperf 自启动的流程+command 实现。
下面先看看 hyperf 源码是怎么实现自启动消费者进程的。
首先我们注意到 Hyperf\Amqp\Listener\BeforeMainServerStartListener 这个监听器,在 BeforeMainServerStart 或者 MainCoroutineServerStart 事件被触发时,Hyperf\Amqp\ConsumerManager::run 方法被执行。
public function process(object $event)
{
// Init the consumer process.
$consumerManager = $this->container->get(ConsumerManager::class);
$consumerManager->run();
}
Hyperf\Amqp\ConsumerManager::run 方法如下:
大致步骤都在图上进行了标注,可以看到整个过程都比较简单。
下面我们参考这个过程,根据 command 来手动创建消费进程。
1、原 consumer 先禁用
【App\Amqp\Consumer\DemoConsumer】enable 设置 false
public function isEnable(): bool
{
return false;
}
2、手动创建一个新的 consumer 用于测试
<?php
declare(strict_types=1);
namespace App\Amqp\Consumer;
use Hyperf\Amqp\Result;
use Hyperf\Amqp\Annotation\Consumer;
use Hyperf\Amqp\Message\ConsumerMessage;
use PhpAmqpLib\Message\AMQPMessage;
class DemoConsumer2 extends ConsumerMessage
{
public $exchange = 'hyperf';
public $routingKey = 'hyperf';
public $queue = 'hyperf';
public function consumeMessage($data, AMQPMessage $message): string
{
print_r($data);
return Result::ACK;
}
public function isEnable(): bool
{
return false;
}
}
在这个 consumer 中,我们手动指定了 exchange、routingKey 和 queue,同时禁止自启动(enable=false)。
3、构建 command
php bin/hyperf.php gen:command DemoConsumerCommand
【App\Command\DemoConsumerCommand】代码如下:
<?php
declare(strict_types=1);
namespace App\Command;
use App\Amqp\Consumer\DemoConsumer;
use App\Amqp\Consumer\DemoConsumer2;
use Hyperf\Amqp\Consumer;
use Hyperf\Command\Command as HyperfCommand;
use Hyperf\Command\Annotation\Command;
use Hyperf\Di\Annotation\AnnotationCollector;
use Psr\Container\ContainerInterface;
use Hyperf\Amqp\Annotation\Consumer as ConsumerAnnotation;
/**
* @Command
*/
#[Command]
class DemoConsumerCommand extends HyperfCommand
{
/**
* @var ContainerInterface
*/
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
parent::__construct('DemoConsumer:command');
}
public function configure()
{
parent::configure();
$this->setDescription('手动启动消费进程测试');
}
public function handle()
{
$consumer = $this->container->get(Consumer::class);
$consumer->consume(make(DemoConsumer2::class));
$this->line('ok.', 'info');
}
}
4、重新启动 hyperf 以及另起一个窗口启动 command
启动 hyperf : php bin/hyperf.php start
启动 command: php bin/hyperf.php DemoConsumer:command
5、测试
浏览器访问 http://127.0.0.1:9501/ ,我们可以在启动 command 的窗口看到消息被成功输出。
hyperf 如何对AMQP消息进行手动消费?的更多相关文章
- RabbitMQ消息发布和消费的确认机制
前言 新公司项目使用的消息队列是RabbitMQ,之前其实没有在实际项目上用过RabbitMQ,所以对它的了解都谈不上入门.趁着周末休息的时间也猛补习了一波,写了两个窗体应用,一个消息发布端和消息消费 ...
- 消息队列手动确认Ack
以RabbitMQ为例,默认情况下 RabbitMQ 是自动ACK机制,就意味着 MQ 会在消息发送完毕后,自动帮我们去ACK,然后删除消息的信息.这样依赖就存在这样一个问题:如果消费者处理消息需要较 ...
- 高可用保证消息绝对顺序消费的BROKER设计方案
转自: http://www.infoq.com/cn/articles/high-availability-broker-design?utm_source=tuicool&utm_medi ...
- 分布式消息队列RocketMQ&Kafka -- 消息的“顺序消费”
在说到消息中间件的时候,我们通常都会谈到一个特性:消息的顺序消费问题.这个问题看起来很简单:Producer发送消息1, 2, 3... Consumer按1, 2, 3...顺序消费. 但实际情况却 ...
- RocketMQ的消息发送及消费
RocketMQ消息支持的模式: 消息支持的模式分为三种:NormalProducer(普通同步),消息异步发送,OneWay. 消息同步发送: 普通消息的发送和接收在前面已经演示过了,在前面的案例中 ...
- springboot集成websocket实现向前端浏览器发送一个对象,发送消息操作手动触发
工作中有这样一个需示,我们把项目中用到代码缓存到前端浏览器IndexedDB里面,当系统管理员在后台对代码进行变动操作时我们要更新前端缓存中的代码怎么做开始用想用版本方式来处理,但这样的话每次使用代码 ...
- RabbitMQ 入门系列:7、保障消息不重复消费:产生消息的唯一ID。
系列目录 RabbitMQ 入门系列:1.MQ的应用场景的选择与RabbitMQ安装. RabbitMQ 入门系列:2.基础含义:链接.通道.队列.交换机. RabbitMQ 入门系列:3.基础含义: ...
- SpringBoot整合RabbitMQ,实现消息发送和消费以及多个消费者的情况
下载安装Erlang和RabbitMQ Erlang和RabbitMQ:https://www.cnblogs.com/theRhyme/p/10069611.html AMQP协议 https:// ...
- rabbitMQ应用,laravel生产广播消息,springboot消费消息
最近做一个新需求,用户发布了动态,前台需要查询,为了用户读取信息响应速度更快(MySQL很难实现或者说实现起来很慢),所以在用户动态发布成功后,利用消息机制异步构建 redis缓存 和 elastic ...
随机推荐
- centos源码安装ruby
目录 一.简介 二.程序部署 一.简介 Ruby,一种简单快捷的面向对象(面向对象程序设计)脚本语言.rvm是ruby的管理器,可以切换ruby版本,下载ruby. 二.程序部署 1.下载ruby w ...
- 转:Android控件属性
Android功能强大,界面华丽,但是众多的布局属性就害苦了开发者,下面这篇文章结合了网上不少资料,花费本人一个下午搞出来的,希望对其他人有用. 第一类:属性值为true或false android: ...
- [BUUCTF]REVERSE——[BJDCTF2020]easy
[BJDCTF2020]easy 附件 例行检查,无壳,32位程序 32位ida载入,main函数和字符串理都没有找到有关flag的提示 根据main函数的提示,有关flag的函数应该被藏起来了,在左 ...
- bjdctf r2t3 onegadget
没错,这就是一篇很水的随笔.... 两道很简单的题,先来看第一道.r2t3,保护检查了一下是只开启了堆栈不可执行. 简单看一下ida的伪代码. main函数让你输入一个name,然后会执行一个name ...
- [BUUCTF]PWN——bjdctf_2020_router
bjdctf_2020_router 附件 步骤: 例行检查,64位程序,开启了NX保护 本地试运行一下程序,看看大概的情况 会让我们选择,选择4.root,没什么用,但是注意了,这边选1会执行pin ...
- 开源企业平台Odoo 15社区版之项目管理应用模块功能简介
项目管理无论是各类证书的认证,如PMP.软考高级的信息系统项目管理师.中级的系统集成项目管理工程师等,还是企业实践都有着广泛的实际应用中,至今还是处于热门的行业,合格的或优化的项目经理还是偏少,对于I ...
- Linux(Centos)内存占用过高处理
查看内存占用最大 ps aux| grep -v "USER" |sort -n -r -k 4 |awk 'NR==1{ print $0}' 命令查看占用内存最大的10个进程 ...
- 更快的Maven来了
Maven经常被拿来和Gradle做对比,最大的劣势之一就是Maven构建慢,Gradle比Maven构建速度快2到10倍,而如今Maven也可以更快了.Apache Maven团队从Gradle和T ...
- Java 8 后的新功能梳理
为什么要写这篇文章 经过了若干年的发展,Java逐步从java8升级为java11,java17. 让我们对比学习一下最新一版的LTS版本和java8比起来让代码简化了多少. 文本块(Text Blo ...
- 【LeetCode】1085. Sum of Digits in the Minimum Number 解题报告(C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 遍历 日期 题目地址:https://leetcode ...