Skip to content

Laravel Crontab 支持的最小单位是分钟,怎么实现秒级执行的需求呢?

「这是我参与11月更文挑战的第23天,活动详情查看:2021最后一次更文挑战

需求描述

今天接到一个需求,每三秒钟给客户端推送一次最新的在线人数。

分析

每三秒钟?要这么频繁吗?之前的最小颗粒度是每分钟哇。

调研了一波发现,我们可以结合异步任务的delay来实现。

核心代码

在 onQueue()函数后面调用 delay()函数

delay指定了延迟多久执行

php
XxxxxJob::dispatch()     ->onQueue(QueueNameBuilder::getName(QueueNameBuilder::PUSH_DATING_COUNT))     ->delay(now()->addSeconds($delay));

需求实现

比如我们的需求是,每三秒钟给客户端推送一次数据。

我的设计是这样的:

异步任务代码

php
<?php namespace App\Console\Crontab; use App\Jobs\PushDatingCountJob; use App\Model\House\HouseOpen; use App\Model\Queue\QueueNameBuilder; class PushDatingCount extends BaseCrontab {     const RATE_SECOND = 3; //每三秒发送一次 延迟实现     public function __invoke()     {         $times = 60 / self::RATE_SECOND;         $delayTimes = [];         for ($i = 0; $i < $times; $i++) {             $delayTimes[] = $i * 3;         }         foreach ($delayTimes as $delay) {             PushDatingCountJob::dispatch()                 ->onQueue(QueueNameBuilder::getName(QueueNameBuilder::PUSH_DATING_COUNT))                 ->delay(now()->addSeconds($delay));         }     } }

Kernel

php
<?php namespace App\Console; . . . class Kernel extends ConsoleKernel {     /**      * The Artisan commands provided by your application.      *      * @var array      */     protected $commands = [         //     ];     /**      * Define the application's command schedule.      *      * @param \Illuminate\Console\Scheduling\Schedule $schedule      * @return void      */     protected function schedule(Schedule $schedule)     {         .         .         .         //每分钟执行一次         $schedule->call(new PushDatingCount())             ->cron("* * * * *")             ->name("push_dating_count")             ->onOneServer();     }     /**      * Register the commands for the application.      *      * @return void      */     protected function commands()     {         $this->load(__DIR__ . '/Commands');         require base_path('routes/console.php');     } }

通过这个思路我们就实现了需求。

更多的使用技巧

本地测试阶段不方面使用异步任务队列怎么办呢?

我们可以使用dispatchNow()

比如:

本地执行,不使用异步队列的情况:

php
UserConfirmForAdmin::dispatchNow([             'data' => $data,             'adminId' => $adminId,         ]);

使用异步任务队列执行的情况:

php
UserConfirmForAdmin::dispatch([             'data' => $data,             'adminId' => $adminId,         ])->onQueue(QueueNameBuilder::getName(QueueNameBuilder::USER_CONFIRM_FOR_ADMIN));

如何可视化查询异步任务的执行情况呢?

我们可以使用 horizon

我们通过仪表盘能够非常方便的进行数据监控,查看数据指标,查看最近失败的异步任务,可以通过后台重新执行异步任务

image.png

重点说一下执行失败的异步任务,后台是支持查看数据参数的,方便我们定位问题。

image.png

硬核文章推荐

PHP转Go 2021年年中总结

如何第一时间收到接口报错?不用测试妹子再质疑你是不是接口挂了。

Git使用实战:多人协同开发,紧急修复线上bug的Git操作指南。

性能优化反思:不要在for循环中操作DB

性能优化反思:不要在for循环中操作DB 进阶版

最后

👍🏻:觉得有收获请点个赞鼓励一下!

🌟:收藏文章,方便回看哦!

💬:评论交流,互相进步!

🚀 学习遇到瓶颈?想进大厂?

看完这篇技术文章,如果还是觉得不够系统,或者想在实战中快速提升?
王中阳的就业陪跑训练营,提供定制化学习路线 + 企业级实战项目 + 简历优化 + 模拟面试。

了解训练营详情