首页 > 其他分享 >3、RabbitMQ队列之工作队列【RabbitMQ官方教程】

3、RabbitMQ队列之工作队列【RabbitMQ官方教程】

时间:2024-12-30 18:09:20浏览次数:9  
标签:教程 false 队列 worker RabbitMQ 消息 php

工作队列

使用 php-amqplib

 在第一个教程中,我们编写了从命名队列发送和接收消息的程序。在本例中,我们将创建一个工作队列,用于在多个工作人员之间分配耗时的任务。

工作队列(又名:任务队列)背后的主要思想是避免立即执行资源密集型任务,并必须等待其完成。相反,我们把任务安排在以后完成。我们将任务封装为消息并将其发送到队列。在后台运行的工作进程将弹出任务并最终执行作业。当你运行多个worker时,任务将在它们之间共享。

这个概念在web应用程序中特别有用,因为在短HTTP请求窗口内无法处理复杂的任务。

准备工作

在本教程的前一部分中,我们发送了一条包含“Hello World!”的消息。现在,我们将发送代表复杂任务的字符串。我们没有现实世界的任务,比如要调整大小的图像或要渲染的pdf文件,所以让我们假装很忙——使用sleep()函数。我们将把字符串中的点数作为其复杂性;每个点将占一秒钟的“工作”。例如,Hello描述的一个假任务。。。需要三秒钟

我们将稍微修改前面示例中的send.php代码,以允许从命令行发送任意消息。这个程序将把任务安排到我们的工作队列中,所以我们把它命名为new_task.php

$data = implode(' ', array_slice($argv, 1));
if (empty($data)) {
    $data = "Hello World!";
}
$msg = new AMQPMessage($data);

$channel->basic_publish($msg, '', 'hello');

echo ' [x] Sent ', $data, "\n";

我们的旧receive.php脚本也需要一些更改:它需要为消息体中的每个点伪造一秒钟的工作。它将从队列中弹出消息并执行任务,因此我们称之为worker.php

$callback = function ($msg) {
  echo ' [x] Received ', $msg->getBody(), "\n";
  sleep(substr_count($msg->getBody(), '.'));
  echo " [x] Done\n";
};

$channel->basic_consume('hello', '', false, true, false, false, $callback);

请注意,我们的假任务模拟了执行时间。

按照教程一中的方式运行它们:

# shell 1
php worker.php
# shell 2
php new_task.php "A very hard task which takes two seconds.."

循环调度

使用任务队列的优点之一是能够轻松并行工作。如果我们正在建立积压的工作,我们可以添加更多的工作人员,这样就可以轻松扩展:

首先,让我们尝试同时运行两个worker.php脚本。它们都会从队列中收到消息,但具体是如何得到的呢?让我们看看。

你需要打开三个控制台。两个将运行worker.php脚本。这些游戏机将是我们的两个消费者——C1和C2

# shell 1
php worker.php
# => [*] Waiting for messages. To exit press CTRL+C
# shell 2
php worker.php
# => [*] Waiting for messages. To exit press CTRL+C

在第三部分中,我们将发布新任务。一旦你启动了消费者,你就可以发布一些消息:

# shell 3
php new_task.php First message.
php new_task.php Second message..
php new_task.php Third message...
php new_task.php Fourth message....
php new_task.php Fifth message.....

让我们看看我们的工人得到了什么:

# shell 1
php worker.php
# => [*] Waiting for messages. To exit press CTRL+C
# => [x] Received 'First message.'
# => [x] Received 'Third message...'
# => [x] Received 'Fifth message.....'
# shell 2
php worker.php
# => [*] Waiting for messages. To exit press CTRL+C
# => [x] Received 'Second message..'
# => [x] Received 'Fourth message....'

默认情况下,RabbitMQ将按顺序将每条消息发送给下一个消费者。平均而言,每个消费者都会收到相同数量的消息。这种分发消息的方式称为轮询。请尝试使用三个或更多工作线程。

消息确认

执行一个任务可能需要几秒钟的时间,你可能会想知道,如果消费者启动了一个长任务,但在完成之前就终止了,会发生什么。使用我们当前的代码,一旦RabbitMQ向消费者发送消息,它就会立即将其标记为删除。在这种情况下,如果终止一个worker,它刚刚处理的消息就会丢失。发送给此特定工作程序但尚未处理的消息也会丢失。

但我们不想失去任何任务。如果一名工人死亡,我们希望将任务交给另一名工人。

为了确保消息永远不会丢失,RabbitMQ支持消息确认。ack(nowledgement)由消费者发回,告诉RabbitMQ已收到、处理了特定消息,并且RabbitMQ可以自由删除它。

如果一个消费者在没有发送ack的情况下死亡(其通道关闭、连接关闭或TCP连接丢失),RabbitMQ将理解消息未完全处理,并将其重新排队。如果同时有其他消费者在线,它将迅速将其重新传递给另一个消费者。这样,即使工人偶尔死亡,你也可以确保没有信息丢失。

消费者交付确认时强制执行超时(默认为30分钟)。这有助于检测从不确认交付的有缺陷(卡住)的消费者。您可以按照“交货确认超时”中的说明增加此超时时间。

消息确认之前是由我们自己关闭的。是时候通过将basic_consume的第四个参数设置为false(true表示没有ack)来打开它们,并在我们完成任务后从worker发送适当的确认。

$callback = function ($msg) {
  echo ' [x] Received ', $msg->getBody(), "\n";
  sleep(substr_count($msg->getBody(), '.'));
  echo " [x] Done\n";
  $msg->ack();
};

$channel->basic_consume('task_queue', '', false, false, false, false, $callback);

使用此代码,您可以确保即使在处理消息时使用CTRL+C终止工作进程,也不会丢失任何内容。在worker终止后不久,所有未确认的消息都会重新传递。

确认必须在收到交付的同一渠道上发送。尝试使用不同的通道进行确认将导致通道级协议异常。请参阅确认文档指南以了解更多信息

错过ack是一个常见的错误。这是一个容易犯的错误,但后果是严重的。当您的客户端退出时,消息将被重新传递(这可能看起来像是随机重新传递),但RabbitMQ将占用越来越多的内存,因为它无法释放任何未标记的消息。

为了调试这种错误,您可以使用 rabbitmqctl 打印 messages_unsacknowledged 字段

sudo rabbitmqctl list_queues name messages_ready messages_unacknowledged

在Windows上,删除sudo:

rabbitmqctl.bat list_queues name messages_ready messages_unacknowledged

消息持久性

我们已经学会了如何确保即使消费者死亡,任务也不会丢失。但如果RabbitMQ服务器停止,我们的任务仍然会丢失。

当RabbitMQ退出或崩溃时,它会忘记队列和消息,除非你告诉它不要这样做。需要做两件事来确保消息不会丢失:我们需要将队列和消息都标记为持久。

首先,我们需要确保队列在RabbitMQ节点重启后能够存活。为了做到这一点,我们需要宣布它是持久的。为此,我们将第三个参数传递给 queue_declare 为 true :

$channel->queue_declare('hello', false, true, false, false);

虽然这个命令本身是正确的,但它在我们目前的设置中不起作用。这是因为我们已经定义了一个名为hello的队列,它是不持久的。RabbitMQ不允许您使用不同的参数重新定义现有队列,并将向任何试图这样做的程序返回错误。但有一个快速的解决方法——让我们用不同的名称声明一个队列,例如task_queue:

$channel->queue_declare('task_queue', false, true, false, false);

设置为true的此标志需要应用于生产者和消费者代码。

此时,我们确信即使RabbitMQ重新启动,task_queue队列也不会丢失。现在我们需要将消息标记为持久。

  • 通过设置 delivery_mode=2 消息属性,AMQPMessage将其作为属性数组的一部分
$msg = new AMQPMessage(
    $data,
    array('delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT)
);

关于消息持久性的说明

将消息标记为持久并不能完全保证消息不会丢失。尽管它告诉RabbitMQ将消息保存到磁盘,但RabbitMQ接受消息但尚未保存消息的时间窗口仍然很短。此外,RabbitMQ不会对每条消息执行fsync(2)——它可能只是保存到缓存中,而不是真正写入磁盘。持久性保证并不强,但对于我们的简单任务队列来说已经足够了。如果你需要更强有力的保证,那么你可以使用出版商确认

公平调度

 

 

官方链接:https://www.rabbitmq.com/tutorials/tutorial-two-php

标签:教程,false,队列,worker,RabbitMQ,消息,php
From: https://www.cnblogs.com/dreamboycx/p/18641913

相关文章

  • 阿里云oss使用教程
    介绍阿里云oss相当于一个在线网盘,帮你存储文件比如你开发网站有个文件上传功能,如果用户上传文件会存到你的服务器,但是服务器的容量是非常有限的,这时就可以接入阿里云oss,把文件上传到阿里云进行存储。参考视频:黑马javaweb2023-03-21发布P148-150苍穹外卖2023-07-05发布......
  • 火爆年终!微信红包封面项目揭秘,零门槛轻松实现日入破千!(附详细教程和渠道)
    大家好,我每天都会分享一个靠谱的副业机会,喜欢我的内容就关注我吧!今天要聊的是年底最赚钱的项目——微信红包封面。年底了,节日一个接一个,像元旦、春节、元宵节、情人节。节日一到,大家都爱发微信红包。现在大家在节日的时候,尤其是春节、情人节,发红包特别有仪式感,所以用个......
  • (免费源码)计算机毕业设计必学必看 万套实战教程 java、python、php、node.js、c#、APP
    摘 要随着社会的发展,社会的各行各业都在利用信息时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。二手车交易平台,主要的模块包括用户后台:首页、车辆评估、我要卖车、卖车订单、试驾申请、购车订单;管理员功能包括:首页、轮播图、公告信息、资源管理(资讯列......
  • 2、RabbitMQ队列之HelloWorld【RabbitMQ官方教程】
    简介1.本教程假设RabbitMQ已安装并在本地主机的标准端口(5672)上运行。如果您使用不同的主机、端口或凭据,则需要调整连接设置。2.如果你在学习本教程时遇到困难,可以通过 GitHubDiscussions或者RabbitMQcommunityDiscord与我们联系RabbitMQ是一个消息代理:它接受和转发消息。......
  • docker自学入门教程
    目录1docker的安装1.1卸载旧版本docker1.2下载相关依赖1.3配置docker的安装源地址1.4安装docker1.5设置开机启动1.6简单命令检验是否安装成功1.7配置镜像加速器(官网属于国外网站,下载镜像会比较慢,推荐阿里云)1.8docker官网的镜像仓库地址2docker基......
  • 保姆级Python安装教程、Pycharm安装教程,附转中文版教程,零基础小白包看包会!
    今天刚好换了新的电脑,需要重新安装一下pyhton和PyCharm,就简单写一个PyCharm安装教程吧。当然Python安装和Pycharm安装包以及资料合集已准备好→点击文字领取一、PyCharm下载1、进入官网:官网地址:https://www.jetbrains.com/2、点击【DeveloperTools】开发者工具,选择......
  • 1、【RabbitMQ官方教程】简介
    简介RabbitMQ是一个开源的消息代理软件(也被称为消息队列),它实现了高级消息队列协议(AMQP)。本教程旨在帮助开发者通过RabbitMQ创建消息应用的基础知识。教程分为两部分:RabbitMQ队列和RabbitMQ流 RabbitMQ队列这部分教程涵盖了默认的RabbitMQ协议AMQP0-9-1。包括以下......
  • Redis可视化工具推荐:Another Redis Desktop Manager下载与详细使用教程
    Redis可视化工具推荐:AnotherRedisDesktopManagerRedis是一种高性能的键值数据库,广泛应用于缓存和消息队列等场景。对于开发者来说,命令行工具固然强大,但操作繁琐。而一款高效易用的可视化工具可以极大地提升使用效率。本篇将为大家推荐一款开源、跨平台且功能强大的Redis可......
  • DataGrip 2024.3安装详细教程与激活方法(附常见问题解决)
    DataGrip概述DataGrip是一款功能强大的,适用于关系数据库和NoSQL数据库的强大跨平台工具温馨提示:本文中的方法仅供学习交流使用,如果条件允许,请支持正版软件。删除旧版本DataGrip如果您的电脑中已经安装了旧版本的DataGrip,建议首先将其完全卸载。操作步骤如下(如果未安装......
  • Beyond Compare v5.0 安装教程(修改版,附激活)
    前言BeyondCompare是一款文件及文件夹(目录)的对比工具。BeyondCompare不仅可以快速比较出两个目录的不同,还可以比较每个文件的内容,而且可以任意显示比较结果。BeyondCompare程序内建了文件浏览器,方便您对文件、文件夹、压缩包、FTP网站之间的差异比对以及资料同步。BeyondCom......