swoole / swoole-src

🚀 Coroutine-based concurrency library for PHP
https://www.swoole.com
Apache License 2.0
18.42k stars 3.16k forks source link

swoole+yii2+zookeeper 定时器高概率出现 swoole_timer: onTimerCallback handler error #1253

Closed lscgzwd closed 7 years ago

lscgzwd commented 7 years ago

样例代码:https://github.com/lscgzwd/briarbear

  1. 检出代码
  2. 拷贝并配置代码中的examples/yii2/storage/config/ini/server.ini 中的信息,包括zookeeper
  3. 配置代码中的examples/yii2/storage/web/start.php中的的配置分离文件,指向第二步的ini文件
  4. 执行php examples/yii2/storage/web/start.php restart
  5. 反复执行以上命令,观察 php_error.log PHP错误日志文件,则可以看到大量报错:
    [26-Jun-2017 11:51:47 PRC] PHP Warning:  Swoole\Server::start(): swoole_timer: onTimerCallback handler error in /mnt/g/workspace/workspace/briarbear/library/briarbear/Server.php on line 347
    [26-Jun-2017 11:51:48 PRC] PHP Warning:  Swoole\Server::start(): swoole_timer: onTimerCallback handler error in /mnt/g/workspace/workspace/briarbear/library/briarbear/Server.php on line 347
    [26-Jun-2017 11:51:49 PRC] PHP Warning:  Swoole\Server::start(): swoole_timer: onTimerCallback handler error in /mnt/g/workspace/workspace/briarbear/library/briarbear/Server.php on line 347
    [26-Jun-2017 11:51:50 PRC] PHP Warning:  Swoole\Server::start(): swoole_timer: onTimerCallback handler error in /mnt/g/workspace/workspace/briarbear/library/briarbear/Server.php on line 347
lscgzwd commented 7 years ago

反复试验,基本排除是zookeeper冲突问题,反而感觉是static静态区的问题,我在代码里面参考YII做了个createObject 实现单例, 单独写测试脚本,连接zookeeper是没有问题的,使用我提供的这份代码就有问题,

GXhua commented 7 years ago

onTimer回调函数报错了,你可以用sleep模拟下ontimer函数,看报啥错,或者手动执行下

lscgzwd commented 7 years ago

不是回调函数的问题,回调函数最顶层有try catch,并且如问题描述,重启第一次失败,第二次正常,也就是只要不出现这个错误,都会执行正常,脱离swoole CLI 单例执行是不出问题的,并且单独用纯PHP写,不用YII写也没有问题,怀疑代码哪个地方不兼容,

lscgzwd commented 7 years ago

进程名被重写了,可以通过 ps aux|grep storage 看进程,可以在params.php中更改serverName来改进程名字

lscgzwd commented 7 years ago

不是一个BUG,原因是我使用了PHP7的强类型,限制 了函数返回类型,但是由于zookeeper 临时节点问题,导致返回的可能类型不对,导致错误,但是不知道为什么这个错误没有被记录进任何日志,最后跟进到zend_call_function 里面有if(EG(exception)) {} 我把该异常打印出来后解决问题。zend_exception_error(EG(exception), E_ERROR);