\Workerman\Lib\Timer 不起作用

秀才

请问

我把一个\Workerman\Lib\Timer放在start_gateway.php中执行,每两秒执行一次,每次执行首先记录一段文字到文本文件。

当我以 php start.php start 的方式运行的时候是没有问题的。
但当我以php start.php start -d 的方式运行的时候好像计时器并没有运行起来。

start_gateway.php代码如下

<?php 
/**
 * This file is part of workerman.
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the MIT-LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @author walkor<walkor@workerman.net>
 * @copyright walkor<walkor@workerman.net>
 * @link http://www.workerman.net/
 * @license http://www.opensource.org/licenses/mit-license.php MIT License
 */
use \Workerman\Worker;
use \Workerman\WebServer;
use \GatewayWorker\Gateway;
use \GatewayWorker\BusinessWorker;
use \Workerman\Autoloader;
use \TySoft\Qian;
use \TySoft\Pushlist;
use \TySoft\Queue;
use \TySoft\Log;

use \Workerman\Lib\Timer;

// 自动加载类
require_once __DIR__ . '/../../Workerman/Autoloader.php';
Autoloader::setRootPath(__DIR__);

$gateway = new Gateway("Websocket://0.0.0.0:8400");
$gateway->name = 'EdisonWeb';
$gateway->count = 4;
$gateway->lanIp = '127.0.0.1';
$gateway->startPort = 2900;
$gateway->registerAddress = '127.0.0.1:1238';
$gateway->pingInterval = 10;
$gateway->pingNotResponseLimit = 2;
$gateway->pingData = '{"type":"ping"}';

$gateway = new Gateway("Text://0.0.0.0:8200");
$gateway->name = 'EdisonText';
$gateway->count = 4;
$gateway->lanIp = '127.0.0.1';
$gateway->startPort = 2800;
$gateway->registerAddress = '127.0.0.1:1238';
$gateway->pingInterval = 10;
$gateway->pingNotResponseLimit = 2;
$gateway->pingData = '{"type":"ping"}';

Timer::add(2, function(){
    $keys=Queue::smembers('Queue');
    $lasttime=time()-7200;
    Log::log('进入计时器循环');
    foreach ($keys as $value) {
        if(Queue::get($value.':addtime')<$lasttime){
            Log::log('需要清除:'.$value);
            $searchinfo=json_decode(Queue::get($value.':info'),true);
            $searchid=$searchinfo;
            $unrecommand_coaches=Queue::sdiff($value.':pushcoache',$value.':recommandcoache');
            Pushlist::clearSearch($value,$searchid);
            $callback="http://zhaosheng.maxiucai.com/api/Search/changeSearchstatus?searchid=".$searchid."&status=cancel";
            Log::log('访问地址:'.$callback);
            $response=file_get_contents($callback);
            Log::log('返回内容:'.$response);
        }
    }
});

if(!defined('GLOBAL_START'))
{
    Worker::runAll();
}

Log.php代码如下

<?php
namespace TySoft;
class Log{
  public static function log($str){
    echo $str."\n";
    file_put_contents('Edison.log', date('Y-m-j G:i:s').$str."\n",FILE_APPEND);
  }
}
5100 6 0
6个回答

walkor 打赏

业务逻辑都要在onXXX回调中运行的(手册中有强调过),换句话说定时器不能在Worker::runAll();执行前运行,因为Worker::runAll();执行前运行的代码都是属于主进程的,主进程不能有业务代码,主进程的业务代码会被子进程继承,导致与预期结果不符。你的例子中可以放到onWorkerStart中运行定时器,建议放到start_businessworker.php中$businessworker->onWorkerStart回调中。

  • 暂无评论
秀才

我用您给的方法确实可以了,但是还有个小问题就是 bussinessWorker进程有4个,但是我只需要一个进程执行这段代码。也就是说我的计时器里的代码两秒执行一次就可以了,在这里执行了四次。有些冗余了。

  • 暂无评论
walkor 打赏

可以判断下worker->id,只在特定ID进程中添加定时器。这部分手册中有,例如
onWorkerStart里面
if($businessworker->id===0){
Timer::add....
}

或者另外一个方法,专门new一个count为1的Worker进程做定时任务

  • 暂无评论
秀才

看来我真得重新好好看看手册了。。。

  • 暂无评论
秀才

新开了一个count为1的进程做定时任务,问题圆满解决!!!感谢walkor大神。

  • 暂无评论
walkor 打赏

不客气

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