毫秒级定时任务

基于Swoole的毫秒定时器,封装的定时任务,取代LinuxCrontab

1.创建定时任务类。

  1. namespace App\Jobs\Timer;
  2. use App\Tasks\TestTask;
  3. use Swoole\Coroutine;
  4. use Hhxsv5\LaravelS\Swoole\Task\Task;
  5. use Hhxsv5\LaravelS\Swoole\Timer\CronJob;
  6. class TestCronJob extends CronJob
  7. {
  8. protected $i = 0;
  9. // !!! 定时任务的`interval`和`isImmediate`有两种配置方式(二选一):一是重载对应的方法,二是注册定时任务时传入参数。
  10. // --- 重载对应的方法来返回配置:开始
  11. public function interval()
  12. {
  13. return 1000;// 每1秒运行一次
  14. }
  15. public function isImmediate()
  16. {
  17. return false;// 是否立即执行第一次,false则等待间隔时间后执行第一次
  18. }
  19. // --- 重载对应的方法来返回配置:结束
  20. public function run()
  21. {
  22. \Log::info(__METHOD__, ['start', $this->i, microtime(true)]);
  23. // do something
  24. // sleep(1); // Swoole < 2.1
  25. Coroutine::sleep(1); // Swoole>=2.1 run()方法已自动创建了协程。
  26. $this->i++;
  27. \Log::info(__METHOD__, ['end', $this->i, microtime(true)]);
  28.  
  29. if ($this->i >= 10) { // 运行10次后不再执行
  30. \Log::info(__METHOD__, ['stop', $this->i, microtime(true)]);
  31. $this->stop(); // 终止此任务
  32. // CronJob中也可以投递Task,但不支持Task的finish()回调。
  33. // 注意:
  34. // 1.参数2需传true
  35. // 2.config/laravels.php中修改配置task_ipc_mode为1或2,参考 https://wiki.swoole.com/wiki/page/296.html
  36. $ret = Task::deliver(new TestTask('task data'), true);
  37. var_dump($ret);
  38. }
  39. // throw new \Exception('an exception');// 此时抛出的异常上层会忽略,并记录到Swoole日志,需要开发者try/catch捕获处理
  40. }
  41. }

2.注册定时任务类。

  1. // 在"config/laravels.php"注册定时任务类
  2. [
  3. // ...
  4. 'timer' => [
  5. 'enable' => true, // 启用Timer
  6. 'jobs' => [ // 注册的定时任务类列表
  7. // 启用LaravelScheduleJob来执行`php artisan schedule:run`,每分钟一次,替代Linux Crontab
  8. // \Hhxsv5\LaravelS\Illuminate\LaravelScheduleJob::class,
  9. // 两种配置参数的方式:
  10. // [\App\Jobs\Timer\TestCronJob::class, [1000, true]], // 注册时传入参数
  11. \App\Jobs\Timer\TestCronJob::class, // 重载对应的方法来返回参数
  12. ],
  13. 'max_wait_time' => 5, // Reload时最大等待时间
  14. ],
  15. // ...
  16. ];

3.注意在构建服务器集群时,会启动多个定时器,要确保只启动一个定期器,避免重复执行定时任务。

4.LaravelS v3.4.0开始支持热重启[Reload]定时器进程,LaravelS 在收到SIGUSR1信号后会等待max_wait_time(默认5)秒再结束进程,然后Manager进程会重新拉起定时器进程。