最新的tp5.1集成workerman提供了两个web_server和socket_server的例子,其中socket_server可以在配置文件中直接设置workerman回调函数,也是很方便的.
不过我个人觉得这样很不方便,不太优雅,这种方式只是把原来workerman的业务代码放到tp5里,如果是我,我会觉得把这部分代码写到控制器里会舒服一些.
并且官方没有给出更灵活的开发workerman的方式,比如我只想用workerman的多进程特性做爬虫,官方的手册没有提供相关例子,所以我在这记录下我的解决方式.
我可以使用下面的命令启动我的爬虫,并且我只需要关注workerman的onworkerstart回调,把业务代码写到控制器里.
php think spider start
自定义指令
详细的做法请参考tp官方手册,这里直接贴步骤.
修改application/command.php
return [
'app\common\command\Spider',
];
新建common模块,command目录,spider类
代码:可以直接复制,我也是在文档上复制下来的
setName('spider')
->addArgument('status', Argument::OPTIONAL, "命令")
->setDescription('spider control');
}
protected function execute(Input $input, Output $output)
{
$status = $input->getArgument('status');
if(!$status){
$output->writeln('pelase input control command , like start');
}
if($status == 'start'){
$output->writeln('start running spider');
$spider = new Start();
foreach (['onWorkerStart', 'onConnect', 'onMessage', 'onClose', 'onError', 'onBufferFull', 'onBufferDrain', 'onWorkerStop', 'onWorkerReload'] as $event) {
if (method_exists($spider, $event)) {
$spider->$event = [$spider,$event];
}
}
$spider->runAll();
}
}
}
代码的基本逻辑:
执行指令,
如果是"start"参数,那么实例化start类(该类继承自worker),
将spider里的方法赋值到worker的属性中,作为回调函数
运行.
自定义类
该类继承worker类,里面设置方法作为workerman的回调,
新建模块spider,控制器start,里面设置onworkerstart等方法.
代码:
基本逻辑:
在这个类里重写了worker的两个方法,否则不能运行.
在onworkerstart里写逻辑即可.
注意:
为什么重写这两个方法:
public static function runAll(){
}
public static function parseCommand(){
}
这两个是worker的基本的方法,按理说不用理会才对,但是我在运行中发现,如果不重写,就不会运行spider模块start类里的方法.
程序运行到parseCommand处,会引入业务文件,其中会判断这个是否有"php"扩展名,没有的话跳过.
在我们运行的"php think spider start"中,think就是我们运行的文件,但这个文件不带有php扩展,workerman就不会把这个文件当做业务文件引入,不会执行其中的逻辑,就是说根本就没运行你写的start类.
并且我发现如果修改think为think.php会报错,暂时不清楚出错的原因.
解决这个问题有两个方法,一个是直接修改worker的parseCommand方法,把这段代码注释掉,就想在上面的代码那样.但是修改vender的内容很粗鲁(很不优雅),所以只有在子类中重写才可以.
那为什么还要重写runAll方法呢?
如上面代码中所示,runAll方法是静态方法,且调用其他静态方法,由于php的后期静态绑定特性,不能重写即:
show();
上面这段代码,如果son类中,没有show方法,输出为"father",只有重写了show方法才会输出"son".
另外:我记得一开始father类中show方法不加static,能输出son,就是说子类的sayMyName重写了父类的方法,但是在项目中并不生效,后来查了手册,发现了这个特性,但是这时无论我怎么做,都不能输出son了,重写show方法才能输出son,好幽灵啊~就想一个假世界一样,我不清楚的内容是随机的,当我清楚之后才是固定的.
因为这个原因,必须重写这两个方法才行.
这样,终于可以把workerman的业务代码写到控制器里.