workerman queue内存使用率持续增高,直到服务器宕机(解决了)

何烈山

问题描述

workerman queue 内存使用率持续增高,直到服务器宕机。
刚开始的时候,单个进程2.43M,然后就一直增高59.04M,直到服务器宕机。
我的服务端没有产生任何的消息列队。就空跑。

reload 后:

过一小段时间后:

程序代码或配置

// ######## 消息队列消费者 ########
$consumer = new Worker();
$consumer->name = 'ImJobConsumer';
// 消费的队列的id
$consumer->queueId = $QUEUE_ID;
// 慢任务,消费者的进程数可以开多一些
$consumer->count = 16;

/**
 * 进程启动阻塞式的从队列中读取数据并处理
 */
$consumer->onWorkerStart = function($consumer)
{
    // 获得队列资源
    $consumer->queue = msg_get_queue($consumer->queueId);
    \Workerman\Lib\Timer::add(0.5, function() use ($consumer){
        if(extension_loaded('sysvmsg'))
        {
            // 循环取数据
            while(1)
            {
                $desiredmsgtype = 1;
                $msgtype = 0;
                $message = '';
                $maxsize = 65535;
                // 从队列中获取消息 @see http://php.net/manual/zh/function.msg-receive.php
                @msg_receive($consumer->queue , $desiredmsgtype , $msgtype , $maxsize , $message, true, MSG_IPC_NOWAIT);
                if(!$message)
                {
                    return;
                }
                // 假设消息数据为json,格式类似{"class":"class_name", "method":"method_name", "args":[]}
                $message = json_decode($message, true);
                // 格式如果是正确的,则尝试执行对应的类方法
                if(isset($message['class']) && isset($message['method']) && isset($message['args']))
                {
                    // 要调用的类名,加上Consumer命名空间
                    $class_name = "\\Consumer\\".$message['class'];
                    // 要调用的方法名
                    $method = $message['method'];
                    // 调用参数,是个数组
                    $args = (array)$message['args'];

                    // 类存在则尝试执行
                    if(class_exists($class_name))
                    {
                        $class = new $class_name;
                        $callback = array($class, $method);
                        if(is_callable($callback))
                        {
                            call_user_func_array($callback, $args);
                        }
                        else
                        {
                            echo "$class_name::$method not exist\n";
                        }
                    }
                    else
                    {
                        echo "$class_name not exist\n";
                    }
                }
                else 
                {
                    echo "unknow message\n";
                }
            }
        }
    });
};

重现问题的步骤

以守护进程的方式启动,然后不断的查看 status,会以肉眼可见的速度增长。

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

Workerman version:4.1.8
PHP version:8.1.7
Distributor ID: Ubuntu
Description: Ubuntu 20.04.4 LTS
Release: 20.04
Codename: focal

P.S. 问题解决了。

我是在消费列队信息的时候,调用Phalcon的Task.

$app = Bootstrap::handle()->app();

由于不断给变量赋值,并没有释放内存。

现在为:

$consumer->onWorkerStart = function($consumer)
{
    // 获得队列资源
    $consumer->queue = msg_get_queue($consumer->queueId);
    $app = Bootstrap::handle()->app();
    \Workerman\Lib\Timer::add(0.5, function() use ($consumer,$app){
        if(extension_loaded('sysvmsg')) {
            $desiredmsgtype = 1;
            $msgtype = 0;
            $message = '';
            $maxsize = 65535;
            @msg_receive(
                $consumer->queue ,
                $desiredmsgtype ,
                $msgtype ,
                $maxsize ,
                $message,
                true,
                MSG_IPC_NOWAIT
            );
807 1 1
1个回答

nitron

在onWorkerStart里每0.5s跑个while(1)我是没想到的

  • 何烈山 2023-02-22

    有问题吗???

  • 何烈山 2023-02-22

    即使去掉while(1) {}:

    use \Workerman\Lib\Timer;

    // 在 onWorkerStart 回调函数中启动一个定时器
    public function onWorkerStart($worker) {
    // 每 0.5 秒执行一次任务
    Timer::add(0.5, function() {
    // 在这里执行您的任务
    // ...
    });
    }

    问题依然存在

  • kspade 2023-02-23

    牛P哈哈

年代过于久远,无法发表回答
🔝