关于优雅退出

dmcz

通过 stop -g 或者 kill -SIGHUP 来优雅结束进程, 接收到信号后在onWorkerStop中该如何处理?等待业务处理完毕后exit还是把所有的连接都销毁掉?在mqtt client中好像并没有可以将$this->_connection设置为null的方法
伪代码


$worker->onWorkerStop = function(){
    /**
     * @var Client
     */
    global $mqtt;

    $mqtt->disconnect();

    exit(0);
};
$worder->onWokerStop = function(){
    global $client;

    $client->destory();
    $client = null;
};
阅读 218
4个回答

walkor

执行到onWorkerStop 一般说明业务已经执行完了,可以直接执行 Worker::stopAll() 退出当前进程,

  • dmcz 12天前

    这样会变成一个死循环把? 接收到信号之后就会执行stopAll, stopAll中执行stop再触发onWorkerStop事件.

  • walkor 12天前

    stopAll内部有判断,不会死循环。

  • dmcz 11天前

    依然还是会死循环,stopAll中 stoping 标记的改变,是再stop()方法之后执行的。还是我使用的方法不太对?代码贴在楼下了。

dmcz

demo:

<?php

use Workerman\Worker;
use Workerman\Mqtt\Client;

require_once('vendor/autoload.php');

var_dump(posix_getpid());

$worker = new Worker('text://127.0.0.1:1234');

$worker->onWorkerStart = function(){
    try {
        $username = 'abc';
        $password = 'abc';
        $clientId = 'abc';

        global $mqtt;

        $mqtt = new Client('mqtt://emqx:1883', [
            'client_id' => $clientId,
            'username' => $username,
            'password' => $password,
            'debug' => true
        ]);

        $mqtt->connect();

    } catch (\Throwable $th) {
        echo (string) $th . PHP_EOL;
        return;
    }
};

$worker->onMessage = function($connection, $buffer){   
    try {
        $data = json_decode($buffer, true);
        if(empty($data)){
            throw new Exception('data error');
        }

        if(empty($data['topic']) || !is_string($data['topic']) || empty($data['message']) || !is_string($data['message']) ){
            throw new Exception('data error');
        }

        global $mqtt;

        $mqtt->publish($data['topic'], $data['message']);

    } catch (\Throwable $th) {
        echo (string) $th . PHP_EOL;
        return;
    }
};

$worker->onWorkerStop = function($worker){
    /**
     * @var Client
     */
    global $mqtt;

    if($mqtt){
        $mqtt->disconnect();
        $mqtt = null;
    }

    Worker::stopAll();
};

Worker::runAll();

也尝试过在 Worker::stopAll() 前将$worker->onWorkerStop=null, 但是此时的连接对象并不会销毁,没有执行连接对象的析构函数里,连接数不会--,进程依然没有结束。

  • 暂无评论
walkor
foreach (\Workerman\Connection\TcpConnection::$connections as $connection) {
    $connection->close();
}

onWorkerStop里这样关闭所有连接,应该就退出了。不用再执行Worker::stopAll();了

  • dmcz 11天前

    在 $mqtt->disconnect();时连接已经被关闭了,但是该连接的对象并没有被销毁,没有在对象的析构函数中减少连接数。

dmcz

多次尝试之后,目前感觉需要在mqtt client中增加一个destory方法用来销毁connection对象。使得连接数在connection对象的析构函数中减一。
worker 伪代码

$worker->onWorkerStop = function($worker){
    /**
     * @var Client
     */
    global $mqtt;

    if($mqtt){
        $mqtt->destory();
        $mqtt = null;
    }
};

mqtt client 伪代码

public function destory(): void
{

        $this->disconnect();

        $this->_connection = $this->onConnect =  $this->onReconnect =  $this->onMessage =  $this->onClose =  $this->onError = null;
}

增加该方法之后 mqtt client 中部分方法可能需要做兼容可能才会更友好,比如close方法中$this->_connection->destroy()前需要对$this->_connection是否为空的判断

  • walkor 11天前

    发个pr吧

  • dmcz 11天前

    ok, 我先在项目改了观察一波