基于Laravel-S集成Swoole实现毫秒级定时任务
Swoole定时器Timer
毫秒精度的定时器。底层基于 epoll_wait
和 setitimer
实现,数据结构使用最小堆
,可支持添加大量定时器。
- 在同步 IO 进程中使用
setitimer
和信号实现,如Manager
和TaskWorker
进程 - 在异步 IO 进程中使用
epoll_wait
/kevent
/poll
/select
超时时间实现
性能
底层使用最小堆数据结构实现定时器,定时器的添加和删除,全部为内存操作,因此性能是非常高的。
差异
Timer
与 PHP
本身的 pcntl_alarm
是不同的。pcntl_alarm
是基于时钟信号 + tick
函数实现存在一些缺陷:
- 最大仅支持到秒,而
Timer
可以到毫秒级别 - 不支持同时设定多个定时器程序
-
pcntl_alarm
依赖declare(ticks = 1)
,性能很差
简单案例第秒执行一次
位置:/www/timer.php
<span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">Swoole\Timer</span>::<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">tick</span>(<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">1000</span>, <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">function</span>(){</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">echo</span> <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">"hello swoole\n"</span>;</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">});</span>
执行结果
<span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">php timer.php </span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">hello swoole</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">hello swoole</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">hello swoole</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">hello swoole</span>
Laravel-S实现定时任务
步骤一:创建一个定时任务类并继承CronJob
位置:app/Jobs/Timer/DemoCronJob.php
<span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important"><?</span><span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">php</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> </span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">namespace</span> <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">App\Jobs\Timer</span>;</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">use</span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">Hhxsv5\LaravelS\Swoole\Timer\CronJob</span>;</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">use</span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">Illuminate\Support\Facades\Log</span>;</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">class</span> <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">TestCronJob</span> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">extends</span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">CronJob</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">protected</span> <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$i</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=</span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">0</span>;</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 每隔 1000ms 执行一次任务</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">public</span> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">function</span> <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">interval</span>()</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> {</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">return</span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">1000</span>; <span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 定时器间隔,单位为 ms</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> }</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 是否在设置之后立即触发 run 方法执行</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">public</span> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">function</span> <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">isImmediate</span>()</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> {</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 是否立即执行第一次,false则等待间隔时间后执行第一次</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">return</span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">false</span>;</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> }</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> </span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 该方法可类比为 Swoole 定时器中的回调方法</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">public</span> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">function</span> <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">run</span>()</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> {</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">Log</span>::<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">info</span>(<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">__METHOD__</span>, [<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'start'</span>, <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$this</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">i</span>, <span style="box-sizing: border-box;color: rgb(232, 191, 106) !important">microtime</span>(<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">true</span>)]);</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$this</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">i</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">++</span>;</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">Log</span>::<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">info</span>(<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">__METHOD__</span>, [<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'end'</span>, <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$this</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">i</span>, <span style="box-sizing: border-box;color: rgb(232, 191, 106) !important">microtime</span>(<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">true</span>)]);</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">if</span> (<span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$this</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">i</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">==</span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">10</span>) { <span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 总共运行3次</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">Log</span>::<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">info</span>(<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">__METHOD__</span>, [<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'stop'</span>, <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$this</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">i</span>, <span style="box-sizing: border-box;color: rgb(232, 191, 106) !important">microtime</span>(<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">true</span>)]);</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 终止此定时任务,但restart/reload后会再次运行</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(224, 108, 117) !important">$this</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-></span><span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">stop</span>();</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> }</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> }</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">}</span>
步骤二:注册定时任务
位置:/config/laravels.php
<span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'timer'</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=></span> [</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'enable'</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=></span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">true</span>,</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'jobs'</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=></span> [</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">\App\Jobs\Timer\DemoCronJob</span>::<span style="box-sizing: border-box;color: rgb(198, 120, 221) !important">class</span>, </span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> ],</span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">'max_wait_time'</span> <span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">=></span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">5</span>, <span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// Max waiting time of reloading</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">],</span>
步骤三:启动laravel-s
位置:项目根目录下
<span style="color: rgb(255, 255, 255);">php bin/laravels start</span><br></br>
步骤四:查看laravel.log日志
位置:storage/logs/laravel.php
<span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">[<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">2021</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-</span><span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">03</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-</span><span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">11</span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">16</span>:<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">28</span>:<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">43</span>] <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">local</span>.<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">INFO</span>: <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">App\Jobs\Timer\DemoCronJob</span>::<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">run</span> [<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">"end"</span>,<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">1</span>,<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">1615480123.445053</span>] </span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">[<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">2021</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-</span><span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">03</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-</span><span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">11</span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">16</span>:<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">28</span>:<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">44</span>] <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">local</span>.<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">INFO</span>: <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">App\Jobs\Timer\DemoCronJob</span>::<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">run</span> [<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">"start"</span>,<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">1</span>,<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">1615480124.442784</span>] </span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(98, 151, 85) !important">// 省略...</span></span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">[<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">2021</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-</span><span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">03</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-</span><span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">11</span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">16</span>:<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">28</span>:<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">53</span>] <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">local</span>.<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">INFO</span>: <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">App\Jobs\Timer\DemoCronJob</span>::<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">run</span> [<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">"end"</span>,<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">11</span>,<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">1615480133.444201</span>] </span><br></br><span style="box-sizing: border-box;color: rgb(171, 178, 191);padding-right: 0.1px">[<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">2021</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-</span><span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">03</span><span style="box-sizing: border-box;color: rgb(86, 182, 194) !important">-</span><span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">11</span> <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">16</span>:<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">28</span>:<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">53</span>] <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">local</span>.<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">INFO</span>: <span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">App\Jobs\Timer\DemoCronJob</span>::<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">run</span> [<span style="box-sizing: border-box;color: rgb(152, 195, 121) !important">"stop"</span>,<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">11</span>,<span style="box-sizing: border-box;color: rgb(209, 154, 102) !important">1615480133.444308</span>]</span>
(完)
请登录后再评论