workerman 队列 内存泄漏

蚂蚁搬家

问题描述

如果我正常运行订阅 没有转发 到队列 就不会出现内存泄漏 如果我转发到队列就会出现内存泄漏为啥呢

程序代码

class Subscribe extends Worker
{
    static $taskName = 'subscribe';
    static $apiConfig;
    static $queue;
    public function __construct($socket_name = '', array $context_option = array())
    {
        parent::__construct($socket_name, $context_option);
    }
    public function on_start($worker)
    {
        global $db_config;
        Db::setConfig($db_config);

        global $redis_config;
        self::$queue = new Client($redis_config['queue']['host'],$redis_config['queue']['options']);

        Utils::echoLogs(self::$taskName.' 启动成功');

        // 作为客户端链接WS
        self::subscribe($list);

    }
    public function on_stop($worker)
    {
        Utils::echoLogs(self::$taskName.' 已停止');
    }
    public function subscribe($data)
    {
        $con = new AsyncTcpConnection(self::$apiConfig['spot_ws']);
        $con->transport = 'ssl';
        $con->websocketPingInterval = 55;
        $con->onMessage = function ($con, $data) {
            // 正常接收Data数据是长期稳定
            // 但是如果我将消息数据组装成新的数组 newData 转发到队列就会出现内存泄漏
            self::$queue->send('data_queue', $newData);
        };
        $con->onError = function ($con, $err_code, $err_msg) {
        };
        $con->onClose = function ($con) {
            $con->reConnect(1);
        };
        $con->connect();
    }
    public function run()
    {
        $this->onWorkerStart = array($this, 'on_start');
        $this->onWorkerStop = array($this, 'on_stop');
        parent::run();
    }
}

报错信息

Worker[2584] process terminated with ERROR: E_ERROR "Allowed memory size of 536870912 bytes exhausted (tried to allocate 69632 bytes) in /mnt/wss/vendor/workerman/workerman/Connection/TcpConnection.php on line 582"
878 2 0
2个回答

damao

你是不是压测时出现的?

  • 蚂蚁搬家 2023-03-09

    不是,我开发测试 执行之后 几分钟之后就出现泄漏啦

walkor

Workerman\RedisQueue\Client 是异步的,消息会先在本地内存里存储,然后一条一条发给Redis服务端。如果产生消息的速度大于redis接收速度(或者redis连不上等),消息就会挤压,占用内存就越来越大。这个其实也不叫内存泄漏。

你可以用同步方式发给redis,这样就不占内存了,参考 https://www.workerman.net/doc/workerman/components/workerman-redis-queue.html#%E5%9C%A8%E9%9D%9Eworkerman%E7%8E%AF%E5%A2%83%E5%90%91%E9%98%9F%E5%88%97%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF

如果是webman项目,直接用 Redis队列同步投递接口

  • 蚂蚁搬家 2023-03-09

    谢谢老大,我现在就是用这个方法,正在测试。

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