请问
我把一个\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);
}
}
业务逻辑都要在onXXX回调中运行的(手册中有强调过),换句话说定时器不能在Worker::runAll();执行前运行,因为Worker::runAll();执行前运行的代码都是属于主进程的,主进程不能有业务代码,主进程的业务代码会被子进程继承,导致与预期结果不符。你的例子中可以放到onWorkerStart中运行定时器,建议放到start_businessworker.php中$businessworker->onWorkerStart回调中。
我用您给的方法确实可以了,但是还有个小问题就是 bussinessWorker进程有4个,但是我只需要一个进程执行这段代码。也就是说我的计时器里的代码两秒执行一次就可以了,在这里执行了四次。有些冗余了。
可以判断下worker->id,只在特定ID进程中添加定时器。这部分手册中有,例如
onWorkerStart里面
if($businessworker->id===0){
Timer::add....
}
或者另外一个方法,专门new一个count为1的Worker进程做定时任务
看来我真得重新好好看看手册了。。。
新开了一个count为1的进程做定时任务,问题圆满解决!!!感谢walkor大神。
不客气