定时任务的进程问题

killhook

centos
workerman 3.0 版
照着手册的定时任务例子做了,没有任何输出。

use \Workerman\Worker;

$task = new Worker();
// 开启多少个进程运行定时任务,注意多进程并发问题
$task->count = 1;
$task->onWorkerStart = function($task)
{
    $time_interval = 2;
    \Workerman\Lib\Timer::add($time_interval, function()
    {
        echo "task run\n";
    });
};

这样做倒是有输出。

\Workerman\Lib\Timer::add(1,function(){echo "task run\n";});

所以我想,是不是进程的问题

$task = new Worker();

那么这个是需要扩展支持还是?

7158 17 1
17个回答

killhook

我看了php -m
pcntl这个是有的

  • 暂无评论
walkor 打赏

代码按照手册规范要放在Applications/项目/start.php中,不知道killhook放在哪里运行的。

例如新建文件Applications/Test/start.php

use \Workerman\Worker;

$task = new Worker();
// 开启多少个进程运行定时任务,注意多进程并发问题
$task->count = 1;
$task->onWorkerStart = function($task)
{
    $time_interval = 2;
    \Workerman\Lib\Timer::add($time_interval, function()
    {
        echo "task run\n";
    });
};

这样表示要建立了一个Worker进程,Worker进程在启动的时候建立了一个定时任务,2秒运行一次,输出 “task run\n”

在workerman根目录运行 php start.php start 运行查看结果

  • 暂无评论
killhook

首先很感谢你的耐心回答
问题确实如你所说,若要建立一个进程的话,这份代码必须放在项目的start.php文件中。
我的是放在自己建立的文件里了,所以不能新建进程,只能添加一个定时任务于当前进程。

另外还有一个问题想请教,我希望在start.php文件里添加一个定时任务,定时执行我自己建立的一个文件里的类里的函数。

但引入路径无论怎么写,都说致命错误,找不到类。
该文件路径为 Applications/项目/MyFunction/TictakEvent.php

TictakEvent.php的代码为

namespace MyFunction;
use \GatewayWorker\Lib\Gateway;
use \GatewayWorker\Lib\Store;

class TictakEvent
{

    public static function renwu_send($name){
        echo $name;
    }

}

按以下方式并不能引入。
use MyFunction\TictakEvent;
$task = new Worker();

$task->count = 1;
$task->onWorkerStart = function($task)
 {
     $time_interval = 3;
     \Workerman\Lib\Timer::add($time_interval, function()
     {
        \MyFunction\TictakEvent::renwu_send(‘test’);
     });
 };
  • 暂无评论
killhook

use \Workerman\Worker; 这个已经引入了,我怕我描述的不够详细。
详细错误是说找不到这个类 \MyFunction\TictakEvent

  • 暂无评论
walkor 打赏

可以更新下workerman
之前Worker没有实现业务类的自动加载,Gateway/Worker是有自动加载的
现在都加上了自动加载,可以试下

  • 暂无评论
killhook

可以了,非常感谢

  • 暂无评论
killhook

你好,之后又产生了新的问题。
已经可以在项目start文件里添加新进程定时运行我自己建立的文件了
在我自己的文件函数里,有用到
Gateway::sendToAll('{"message":"hehe","type":"test"}',$user_list);
但使用时报错

PHP Warning:  Invalid argument supplied for foreach() in /home/www/workerman/GatewayWorker/Lib/Gateway.php on line 54

$user_list 我var_dump出来是有值的。

array(2) {
  =>
  int(4)
  =>
  int(3)
}

但不知为何,传入sendToAll后,我在Gateway文件里加入了var_dump的语句来检查我传入的数组,结果却是
bool(false)

  • 暂无评论
killhook

我可以确认,我的数组里的用户是在线的。

  • 暂无评论
walkor 打赏

我这测试没有问题,这里是start.php的全部代码

<?php
use \Workerman\WebServer;
use \GatewayWorker\Gateway;
use \GatewayWorker\BusinessWorker;
use \Workerman\Lib\Timer;
use \Workerman\Worker;

// gateway
$gateway = new Gateway("Websocket://0.0.0.0:8585");

$gateway->name = 'TodpoleGateway';

$gateway->count = 4;

$gateway->lanIp = '127.0.0.1';

$gateway->startPort = 4000;

$gateway->pingInterval = 10;

$gateway->pingData = '{"type":"ping"}';

// bussinessWorker
$worker = new BusinessWorker();

$worker->name = 'TodpoleBusinessWorker';

$worker->count = 4;

// ##############让一个小蝌蚪定时说hello 开始#########
$task = new Worker();
$task->onWorkerStart = function($task){
    Timer::add(5, function(){
        $client_list = \GatewayWorker\Lib\Gateway::getOnlineStatus();
        \GatewayWorker\Lib\Gateway::sendToAll(json_encode(array('type'=>'message', 'id'=>current($client_list), 'message' => 'hello')));
    });
};
// ##############让一个小蝌蚪定时说hello 完毕#########

// WebServer
$web = new WebServer("http://0.0.0.0:8686");

$web->count = 2;

$web->addRoot('www.your_domain.com', __DIR__.'/Web');

你可以自己var_dump定位下是哪里的问题,问题应该很好找

  • 暂无评论
killhook

你的代码我测试下来是没有问题的
我的代码放到项目/Event.php里于当前进程执行也是没有问题的
但是一旦放在我自己新建的文件里,问题就出来了。
经过跟踪调试发现,在\GatewayWorker\Lib\Gateway.php 文件的第42行起
如果是在项目的start.php文件里做的新建进程或者是在项目的Event.php里做的添加至当前进程,
在执行sendToAll时,self::$businessWorker为真,执行if里的语句
而如果是在项目start.php里新建进程去定时调用我自己建立的文件里的函数。
这个函数在执行sendToAll时,self::$businessWorker为假,执行的是else里的语句。
我想这就是问题所在吧。。

// 如果有businessWorker实例,说明运行在workerman环境中,通过businessWorker中的长连接发送数据
if(self::$businessWorker)
{
    foreach(self::$businessWorker->gatewayConnections as $gateway_connection)
    {
        $gateway_connection->send($gateway_data);
    }
}
// 运行在其它环境中,使用udp向worker发送数据
else
{
    $all_addresses = Store::instance('gateway')->get('GLOBAL_GATEWAY_ADDRESS');
    foreach($all_addresses as $address)
    {
        self::sendToGateway($address, $gateway_data);
    }
}
  • 暂无评论
walkor 打赏

但是一旦放在我自己新建的文件里,问题就出来了。

这种情况是因为一个项目是基于Gateway/Worker的,另外一个项目是基于Worker的,Workerman/Applications下的多个项目是不相干的,Worker项目里面找不到Gateway/Worker的配置导致

解决办法:
可以手动require_once下Gateway/Worker项目下的Config/Store.php试下

  • 暂无评论
killhook

经过尝试在项目里包含配置文件,这没有解决问题。

  • 暂无评论
killhook

先把代码放start.php里跑起来再说吧。暂时不想折腾这个问题了。。。。

  • 暂无评论
killhook

非常感谢你的耐心回答。

  • 暂无评论
killhook

walkor,我郑重的向你道歉,我始终还是咽不下定时进程这口气,盯着你的源码看了良久,又在脑海里把Gateway/Worker 的进程模型翻来覆去的想。终于明白。都是我的错,为了便于调试,我在我自己的业务处理类里的客户登陆那加入了以下代码。
$store = Store::instance('room');
$store->flush();
这样,你的Gateway.php又哪里能取到值。。。。。
$all_addresses = Store::instance('gateway')->get('GLOBAL_GATEWAY_ADDRESS');

非常抱歉。以及感谢你的耐心和专业。

  • 暂无评论
killhook

现在代码已经在愉快的正常工作了。

  • 暂无评论
walkor 打赏

好的

  • 暂无评论
年代过于久远,无法发表回答
×
🔝