GatewayWorker 在多进程下怎么创建唯一的全局定时器?

ximengxuan

如何设置全局唯一的定时器

由于GatewayWorker/Applications/YourApp/start_businessworker.php里设置的进程数量是4

$worker->count = 4;

Events.php文件的onWorkerStart事件里设置了一个定时器。

public static function onWorkerStart($businessWorker){
        // 每N秒执行一次
        $time_interval = 60;
        Timer::add($time_interval, function () {
            echo "[" . date("m-d H:i:s") . "] " . 'onWorkerStart 分钟定时器' . "\n";

            # 进行同步或者异步的数据库写入操作
        });
}

重启服务后,会连续打印4条数据。说明定时器执行了4次。

[10-06 18:27:15] onWorkerStart 分钟定时器
[10-06 18:27:15] onWorkerStart 分钟定时器
[10-06 18:27:15] onWorkerStart 分钟定时器
[10-06 18:27:15] onWorkerStart 分钟定时器

要在定时器内执行异步的数据库写入操作,如何让多进程下,只有一个全局定时器呢?

数据库连接的次数

Event::onWorkerStart里设置了mysql和Redis数据库的初始化配置。
如果有4个businessworker进程,这里就会初始化4次。

重复的配置和初始化,会不会造成资源浪费呢?
能不能只初始化一次,全局所有的onMessage事件里就可以用呢。

161 2 0
2个回答

ximengxuan

找到一个解决的办法,仅供参考。如果有更好的办法,欢迎提出来。

先在Events.php里创建一个测试函数

    public static function test()
    {
        echo "[" . date("m-d H:i:s") . "] " . 'Events 内的定时执行的方法' . "\n";

        // 这里可以引用类里面的一些变量和方法,执行定时操作

    }

然后在start_worker.phponWorkerStart里创建一个定时器,调用Events.php里的测试方法

require_once 'Events.php';

$task_worker->onWorkerStart = function ($worker) {

    // 每N秒执行一次
    $time_interval = 60;
    Timer::add($time_interval, function () {
        echo "[" . date("m-d H:i:s") . "] " . 'onWorkerStart 独立的分钟定时器' . "\n";

        // 测试定时调用
        $Events = new Events();
        $Events->test();

    });
};

实测这个定时器是单进程的,每分钟会执行一次。而不是每分钟连续执行4次

然而、但是,上面这个简单的例子是可以执行的。
写了个复杂点的,在定时器里执行Redis写入操作,就报错了:

Warning: stream_socket_client(): unable to connect to tcp://127.0.0.1:1236 (Connection refused) in /GatewayWorker/vendor/workerman/gateway-worker/src/Lib/Gateway.php on line 1346
[10-06 19:34:18] onWorkerStart  Error:Exception: Can not connect to tcp://127.0.0.1:1236 Connection refused in /GatewayWorker/vendor/workerman/gateway-worker/src/Lib/Gateway.php:1352
Stack trace:

看来这个方法还是不能做数据库操作啊。期待更好的办法。

  • 暂无评论
小Z先生

试试这样


public static function onWorkerStart($businessWorker){
        if(businessWorker->id ==0){
            // 每N秒执行一次
            $time_interval = 60;
            Timer::add($time_interval, function () {
                echo "[" . date("m-d H:i:s") . "] " . 'onWorkerStart 分钟定时器' . "\n";

                # 进行同步或者异步的数据库写入操作
            });
        }
}
×
🔝