我使用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();
}
}
你这种做法类似于想复制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服务类名 支持数组定义多个服务
如果没有指定Worker::$pidFile,workerman会根据启动的文件名字来生成一个pid文件,thinkphp命令行里就是用thinkphp来自动生成一个pid文件。这样当执行stop status等命令时,就能找到主进程的pid,才能和对应的进程交互。
php think PriceOkex start
、php think PriceBinance start
这2个命令使用的是相同的thinkphp文件,所以pid一样,无法重复启动。解决办法是根据参数不同,设置不同的Worker::$pidFile。
比如
php think PriceOkex start
时代码里动态设置Worker::$pidFile = '/var/run/PriceOkex.pid';
,这样用thinkphp命令行启动多个服务,互相不影响。我在laravel 5.5 commands中使用Workerman遇到了同样的问题,两个不同的command,都设置了各自不同的pidFile,但是在使用 php artisan 启动其中一个时,另外一个也会被启动,此时只有一个pidFile生成,但是两个command中的Worker进程都被启动了
应该全部写成servers,然后A::run();B::run();Worker::runAll();
感谢各位帮助! 谢谢
你这个问题解决了吗,我在laravel中遇到了同样的问题,并且设置pidFile也不起作用