webman reload 平滑重启,导致 redis 消费者进程正在处理的消息丢失

oliver.

问题描述

项目发版执行 php start.php reload 重启服务时,如果 redis 消费者进程正在处理消息,会导致这些消息丢失。
请问各位大佬,在不改 webman/redis-queue 插件源码的情况下,有办法解决这个问题吗?还是说只能换专业的 MQTT 服务了?

消费者进程的演示代码

<?php

namespace app\queue\redis;

use support\Log;
use Webman\RedisQueue\Consumer;

class TestConsume implements Consumer
{
    public $queue = 'test-consume';

    public $connection = 'default';

    public function consume($data)
    {
        Log::info('@@@@@@@start');
        for ($i = 0;$i < 10;$i++) {
            sleep(1);
        }
        Log::info('@@@@@@@end');
    }
}

重现问题的步骤

  • 投递消息
    Redis::send('test-consume', []);
  • 监控日志文件
    tail -f runtime/logs/webman-2025-01-09.log
    #输出
    [2025-01-09 09:54:33] default.INFO: @@@@@@@start [] []
  • 在消费者进程执行过程中,重启 webman 服务
    php start.php reload
  • 我原本预期 webman 服务平滑重启时,会将消费者进程执行一半的消息重入队列,重启完成后,这些消息将再次被执行,但测试验证结果并非如此(项目的日志文件没有执行日志)。

操作系统环境及workerman/webman等具体版本

Linux CentOS 7
PHP 8.2.22
Webman-framework v1.5.24
webman/redis-queue v1.3.2
Redis Version: 7.0.11

354 5 0
5个回答

zz1000

文档不是有吗 配置进程退出的等待时间

  • oliver. 6天前

    感谢您的回复。尽管这并不能完全解决消息丢失的问题,但只要将退出等待时间设置得足够长,还是可以在很大程度上避免出现这个问题的。

nitron

对消息丢失有强要求就使用正儿八经的消息队列

  • 暂无评论
chaz6chez
rbb

也可以单独开一个消费队列出来,不同于你的api项目上。这样频繁更新代码,不影响你消费者服务

  • 暂无评论
释永战

我都是另外开一个队列work实例服务来执行的

  • oliver. 5天前

    你是基于 workerman/redis-queue 组件,自定义了一个命令创建 work 实例并订阅消费 redis 队列消息么

  • nitron 5天前

    他意思是,再开一个完整的项目只进行消费吧

  • 释永战 5天前

    对的,另外开了一个项目只进行消费业务

  • oliver. 4天前

    那同一个项目不得维护两套相同的代码,除非消费者程序没有引用 API 项目的功能模块

  • 小白同学丶 1天前

    怎么能用2套相同代码。 你单独处理队列任务就可以了吧。。

    以前我们用workerman做游戏时候。4套代码。。都不一样,任务也不一样。 如果非要一样的话。 那顶多重啊?

×
🔝