workerman与TP框架command结合,只能执行一个worker 文件的问题

vasileon

我使用TP框架的command 结合 workerman 来使用。
具体是在command里新建2个文件,然后通过php think PriceOkex start 、php think PriceBinance start 来启动,发现只能启动一个,另一个直接报错说worker已经在执行了。报错内容
Workerman[think] start in DEBUG mode
Workerman[think] already running
应该是 入口文件 think 重名了,有没有什么方式让workerman 以 think文件后面一个参数(比如上面的PriceOkex、PriceBinance)作为这个key ?

文件内容如下

<?php
declare (strict_types=1);
namespace app\command;
use Workerman\Connection\AsyncTcpConnection;
use Workerman\Worker;

class PriceOkex extends Command
{
    protected function configure()
    {
        // 指令配置
        $this->setName('PriceOkex')
            ->addArgument('action', Argument::OPTIONAL,
                "start|stop|restart|reload|status|connections", 'start')
            ->addOption('mode', 'm', Option::VALUE_OPTIONAL,
                'Run the workerman server in daemon mode.')
            ->setDescription('the workerman command');
    }
    protected function execute(Input $input, Output $output)
    {
        // 指令输出
        $output->writeln('convert start');
        $action = $input->getArgument('action');
        $mode = $input->getOption('mode');
        // 重新构造命令行参数,以便兼容workerman的命令
        global $argv;
        $argv = [];
        array_unshift($argv, 'think', $action);
        if ($mode == 'd') {
            $argv[] = '-d';
        } else {
            if ($mode == 'g') {
                $argv[] = '-g';
            }
        }
        $worker_1 = new Worker();
        $worker_1->name = 'PriceOkex';
        $worker_1->id = 2;
        $worker_1->onWorkerStart = function ($worker) {
            $pRedis = Predis::getInstance();
            $con = new AsyncTcpConnection('ws://ws.okx.com:8443/ws/v5/public');
            $con->transport = 'ssl';
            $con->onConnect = function (AsyncTcpConnection $con) {
            };
            $con->onMessage = function (AsyncTcpConnection $con, $data) use (
                $pRedis
            ) {
            };
            $con->connect();
        };
        Worker::runAll();
    }
}

另一个文件如下

<?php
declare (strict_types=1);
namespace app\command;
use Workerman\Connection\AsyncTcpConnection;
use Workerman\Worker;

class PriceBinance extends Command
{
    protected function configure()
    {
        // 指令配置
        $this->setName('PriceBinance')
            ->addArgument('action', Argument::OPTIONAL,
                "start|stop|restart|reload|status|connections", 'start')
            ->addOption('mode', 'm', Option::VALUE_OPTIONAL,
                'Run the workerman server in daemon mode.')
            ->setDescription('the workerman command');
    }

    protected function execute(Input $input, Output $output)
    {
        // 指令输出
        $output->writeln('convert start');
        $action = $input->getArgument('action');
        $mode = $input->getOption('mode');
        // 重新构造命令行参数,以便兼容workerman的命令
        global $argv;
        $argv = [];
        array_unshift($argv, 'think', $action);
        if ($mode == 'd') {
            $argv[] = '-d';
        } else {
            if ($mode == 'g') {
                $argv[] = '-g';
            }
        }
        $worker_1 = new Worker();
        $worker_1->name = 'PriceBinance';
        $worker_1->id = 1;
        $worker_1->onWorkerStart = function ($worker) {
            $pRedis = Predis::getInstance();
            $con
                = new AsyncTcpConnection('ws://stream.binance.com:9443/ws/btcusdt@aggTrade');
            $con->transport = 'ssl';
            $con->onConnect = function (AsyncTcpConnection $con) {
            };
            $con->onMessage = function (AsyncTcpConnection $con, $data) use (
                $pRedis
            ) {
            };
            $con->connect();
        };
        Worker::runAll();
    }
}
3445 4 0
4个回答

2548a

你这种做法类似于想复制N份 start.php ,然后想
php start.php start -d
php start1.php start -d
php start2.php start -d

按我个人理解,你这种做法是不正确的,thinkphp里面,如果想定义多个worker 服务,
,正确做法是在配置的worker_class 里面设置自定义服务
'worker_class' => [],
// 自定义Workerman服务类名 支持数组定义多个服务

  • 暂无评论
walkor

如果没有指定Worker::$pidFile,workerman会根据启动的文件名字来生成一个pid文件,thinkphp命令行里就是用thinkphp来自动生成一个pid文件。这样当执行stop status等命令时,就能找到主进程的pid,才能和对应的进程交互。

php think PriceOkex startphp think PriceBinance start 这2个命令使用的是相同的thinkphp文件,所以pid一样,无法重复启动。

解决办法是根据参数不同,设置不同的Worker::$pidFile。
比如php think PriceOkex start时代码里动态设置 Worker::$pidFile = '/var/run/PriceOkex.pid';,这样用thinkphp命令行启动多个服务,互相不影响。

  • zijin 2022-06-18

    我在laravel 5.5 commands中使用Workerman遇到了同样的问题,两个不同的command,都设置了各自不同的pidFile,但是在使用 php artisan 启动其中一个时,另外一个也会被启动,此时只有一个pidFile生成,但是两个command中的Worker进程都被启动了

admin

应该全部写成servers,然后A::run();B::run();Worker::runAll();

  • 暂无评论
vasileon

感谢各位帮助! 谢谢

  • zijin 2022-06-18

    你这个问题解决了吗,我在laravel中遇到了同样的问题,并且设置pidFile也不起作用

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