tp5使用RabbitMQ的使用记录(二)-- work queue

tp5使用RabbitMQ的使用记录

 rabbitmq 官方文档 work queue 的部分

首先希望大家能够关注文档,文档上的内容比较全面,解释的也非常形象。我对此的记录就是写了一下对文档的理解,并且把文档上的内容在TP5中由重新写了一遍。

work queue 工作队列又称为任务队列,我认为这种模式的队列有一下几点是需要关注的。

        - 需要明确的是一个队列可以被多个消费者消费
        - 在被多个消费者消费的情况下,一个队列里的100个元素会被平均的分配到n个消费者那里。循环调度
        - 平均分配到n个消费者那里就会产生一个情况: 100个分到2个消费者那里, 每个消费者各自收获了50个, 第一个消费者把50个任务消费完了。第二个消费者消费到第十个任务的时候,进程挂掉了。所以还剩下40个任务在消费者2这个通道里。就会导致任务的丢失。为了确保消息永远不会丢失,所以,rabbitmq增加了消息确认机制。
       - 消息的持久化 消息的持久化要保证channel和queue 的持久化参数都是开启状态。 只开启chanel的持久化肯定是不起作用的。(不能再已有的队列名称的channel中再开一个名字相同的queue。)
          - 公平调度 如果有多个消费者, 每个消费者处理任务的速度不一样,为了要做到公平调度,也就是执行任务快的多做一点任务,这行任务慢的少做一些任务。

app\controller\Test.php

<?php
/**
 * Created by Fanguochao
 * User: fgc
 * Date: 2021-08-23
 * Time: 21:52
 * Desc: rabbimtMQ测试类
 */

namespace app\controller;

use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Connection\AMQPStreamConnection;

use app\Library\RabbimtMQConnection;

class Test
{
    
    // 工作队列
    public function work(){
        // 创建新的链接器
        $connection = new AMQPStreamConnection('localhost', '5672', 'guest', 'guest');
        // 创建通道
        $channel = $connection->channel();

        // 创建队列 durable对应true表示开启持久化,当然只设置这一个并没有用
        // 需要对消息也设置一个参数 就是50行的 array('delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT)
        $channel->queue_declare('task_queue', false,true,false,false);

        // 循环创建10条消息
        for($i=0 ;$i<10;$i++){
            $data = "$i Hello World!";

            // TODO 初始化消息 待完善
            $msg = new AMQPMessage($data, array('delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT));

            // 往消息队列里面发送消息
            $channel->basic_publish($msg, '','task_queue');
        }

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

        // 关闭连接
        $channel->close();
        $connection->close();
    }
}

相关的路由请求文件

这两个文件写完以后,发起一个请求

看到这一句话后,到rabbitmq管理网站上看队列里面有没有数据

接下来我们就要消费这个数据

因为消费数据是需要不断监听rabbitmq服务器传过来的数据,所有我选择有执行命令行来监听服务器。后期就可以执行这个命令脚本了。

app\Command\Recevie.php

<?php
declare (strict_types=1);

namespace app\command;

use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;

use PhpAmqpLib\Connection\AMQPStreamConnection;
use app\Library\RabbimtMQConnection;
use PhpAmqpLib\Message\AMQPMessage;

class Receive extends Command
{
    protected function configure()
    {
        // 指令配置
        $this->setName('receive')
            ->setDescription('rabbitmq 消费队列');
    }

    protected function execute(Input $input, Output $output)
    {
        // 指令输出
        $output->writeln("RabbitMQ 消费队列开始启动……\n");

        // 创建连接
        $connection = new AMQPStreamConnection('localhost', '5672', 'guest', 'guest');
        // 创建通道
        $channel = $connection->channel();

        //创建队列 durable对应true表示开启持久化,当然只设置这一个并没有用
        $channel->queue_declare('task_queue', false,true,false,false);

        $output->writeln("RabbitMQ 创建通道成功……\n");
        $output->writeln("[*] Waiting for messages. To exit press CTRL+C\n");

        $callback = function ($msg) use ($output) {

            $output->writeln("通过RabbitMQ获取到消费者了,该条消息是: $msg->body \n");
            // 消息确认机制 如果不写这一句话的话,在消息队列的unacked那一列就会产生一个未被确认的消息
            $msg->ack();
        };

        // 一个消费者只能获取一个消息队列中的消息,保持消息的完整性和安全性。防止一个消费者获取多个消息,在处理的过程中宕机导致数据丢失
        $channel->basic_qos(null, 1, null);
        $channel->basic_consume('task_queue', '', false, false, false, false, $callback);


        while ($channel->is_open()) {
            $channel->wait();
        }
    }

}

 

产生这个的原因是下面这一段代码

$channel->basic_qos(null, 1, null);

 也就是说在处理并确认前一条消息之前,不要向发送新消息,相反,它会将它分派给下一个不忙的消费者。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值