laravel异步监控定时调度器实例详解


Posted in PHP onJune 21, 2019

定时调度器是什么

laravel默认提供了一个命令定时任务的功能,在其他的php框架下面,没有这个定时任务,我们要跑一些异步脚本怎么操作呢,只能依赖我们系统提供的crontab来做,这就导致我们每次发版本新增定时任务都要去服务器更改crontab代码,获取更新这个配置。

执行命令是php artisan schedule:run 来执行,那放在哪里执行呢,没错这个调起还是需要依赖我们crontab来执行,但是只需要配置一次,后续所有定时任务都在我们业务代码进行控制

场景

我们有一个导入数据的定时任务

//每分钟导入库数据
$schedule->command(self::SIGNATURE)->withoutOverlapping()->everyMinute()->runInBackground();

这里导入长时间最好使用runInBackground(),表示异步执行,其实就是在shell脚本的末尾加上 & 符号,在linux上完全依赖系统的方式完成。

这里使用了withoutOverlapping() 表示在同一时刻只能有一个任务执行,主要逻辑使用的是排它锁实现,依赖于我们cache的driver,我这里使用的是redis,后面作为锁的过期直接redis提供的key过期来做。

出现问题

这个任务在正常情况下都是非常完美的,因为同一时刻只有一个再跑,跑完就可以,但是一个场景出现
有一天我们的qa同学刚部署环境后,我们服务端就在默默的导入库了,因为使用withoutOverlapping($expire_at=1440)这个时候在redis就有一个锁产生了,这个默认带参数是锁的过期时间,默认是一天,然后因为我们docker环境需要更改参数然后进行后端server服务的重启,我们重启也是比较暴力,就是直接发送kill的信号,导致所有在里面跑的进程瞬间kill,而这时候我们的redis的锁缺还存在,而且是1440分钟左右,那当我们server再启动后,发现锁一直存在,没办法进行后续的操作了,只能等着。

解决

那我把锁的时间减少行不行,原来1天,我改成30分钟,没问题,开始第一版方案我们也是这样做,官方也是可以这样做的。

后来我们一想,能否做到一个监控程序呢,进程退出后立马监控到过期呢,这样就不用固定一个时间,这当然是所有软件开发者理想状态:要你开你就开,我挂了锁也就去掉了,不论正常与否。

解决方案

laravel异步监控定时调度器实例详解

说明:

  • 这里命令启动时候,获取进程的pid,然后fork子进程,可以将这个pid传递给子进程。
  • 子进程每隔10s进行一个探活,获取父进程的id与传入的pid是否一致,这里普及一个知识点,如果父进程异常退出,这个子进程未退出就会被init进程(pid=1)接管,那么这就是一个孤儿进程。
  • 同时子进程每次探活的时候就会更改redis的锁的过期时间,如果探活时间间隔是10s,那么我们的过期时间设置就是14s,多冗余一点时间。

代码实现

代码实现总是那么苍白无力哈,这里就写一个laravel的扩展来做,好处就是不影响我们主体的任何代码就完成了,我们的laravel可以随意升级。

github地址:github.com/zzh78727258…

composer地址:packagist.org/packages/ze…

总结

整体实现没有使用判断进程是否存在的ps grep等命令,因为我们docker环境不一定支持这些命令,只是用简单的pid与parent_id做对比。

laravel的在命令开始于结束都进行钩子方式,我们在Listener下面进行监听即可

public function subscribe($events)
 {
  $events->listen(
   [
    CommandStarting::class, // 命令开始的时候
   ],
   __CLASS__ . '@handle'
  );
 }

整体代码是基于laravel扩展化的,不会影响laravel的升级操作。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
PHP下10件你也许并不了解的事情
Sep 11 PHP
php关于array_multisort多维数组排序的使用说明
Jan 04 PHP
基于MySQL分区性能的详细介绍
May 02 PHP
win7+apache+php+mysql环境配置操作详解
Jun 10 PHP
Symfony页面的基本创建实例详解
Jan 26 PHP
PHP多线程之内部多线程实例分析
Mar 09 PHP
PHP列出MySQL中所有数据库的方法
Mar 12 PHP
php文件操作小结(删除指定文件/获取文件夹下的文件名/读取文件夹下图片名)
May 09 PHP
PHP实现十进制、二进制、八进制和十六进制转换相关函数用法分析
Apr 25 PHP
详解如何在云服务器上部署Laravel
Jun 30 PHP
PHP实现的MD5结合RSA签名算法实例
Oct 07 PHP
thinkphp 中的volist标签在ajax操作中的特殊性(推荐)
Jan 15 PHP
apache集成php7.3.5的详细步骤
Jun 20 #PHP
PHP基础之输出缓冲区基本概念、原理分析
Jun 19 #PHP
PHP进阶学习之Geo的地图定位算法详解
Jun 19 #PHP
PHP进阶学习之依赖注入与Ioc容器详解
Jun 19 #PHP
yii2 在控制器中验证请求参数的使用方法
Jun 19 #PHP
php自定义排序uasort函数示例【二维数组按指定键值排序】
Jun 19 #PHP
windows 2008r2+php5.6.28环境搭建详细过程
Jun 18 #PHP
You might like
肝肠寸断了解下!盘点史上最伤心的十大动漫
2020/03/04 日漫
PHP合并数组+与array_merge的区别分析
2010/08/01 PHP
php检查字符串中是否包含7位GSM字符的方法
2015/03/17 PHP
Zend Framework实现多服务器共享SESSION数据的方法
2016/03/22 PHP
JS日历 推荐
2006/12/03 Javascript
用js实现的一个Flash滚动轮换显示图片代码生成器
2007/03/14 Javascript
网页禁用右键实现代码(JavaScript代码)
2009/10/29 Javascript
jquery png 透明解决方案(推荐)
2010/08/21 Javascript
JavaScript Array Flatten 与递归使用介绍
2011/10/30 Javascript
基于JavaScript FileReader上传图片显示本地链接
2016/05/27 Javascript
全面解析JavaScript中的valueOf与toString方法(推荐)
2016/06/14 Javascript
基于Marquee.js插件实现的跑马灯效果示例
2017/01/25 Javascript
详解用node-images 打造简易图片服务器
2017/05/08 Javascript
JavaScript中的return布尔值的用法和原理解析
2017/08/14 Javascript
Js利用Canvas实现图片压缩功能
2017/09/13 Javascript
jQuery实现的监听导航滚动置顶状态功能示例
2018/07/23 jQuery
vue主动刷新页面及列表数据删除后的刷新实例
2018/09/16 Javascript
vue中使用v-for时为什么不能用index作为key
2020/04/04 Javascript
vue data变量相互赋值后被实时同步的解决步骤
2020/08/05 Javascript
[01:45]DOTA2新英雄“神谕者”全方位展示
2014/11/21 DOTA
Python的Flask框架应用程序实现使用QQ账号登录的方法
2016/06/07 Python
浅谈Python基础之I/O模型
2017/05/11 Python
python pycurl验证basic和digest认证的方法
2018/05/02 Python
Python使用sklearn库实现的各种分类算法简单应用小结
2019/07/04 Python
python生成特定分布数的实例
2019/12/05 Python
tensorflow之获取tensor的shape作为max_pool的ksize实例
2020/01/04 Python
Python自动创建Excel并获取内容
2020/09/16 Python
大学四年规划书范文
2013/12/27 职场文书
美德好少年事迹材料
2014/01/19 职场文书
优秀毕业生自我鉴定
2014/02/11 职场文书
自我鉴定总结
2014/03/24 职场文书
食品销售计划书
2014/04/26 职场文书
2014年母亲节演讲稿范文
2014/05/07 职场文书
2015年监理工作总结范文
2015/04/07 职场文书
通知的写法
2015/04/23 职场文书
小学见习报告
2015/06/23 职场文书