php互斥插件_php插件开发

线上业务经常会用到邮件系统php互斥插件,假设在没有使用异步消息队列(最常用的方式)处理的情况下,使用php脚本+crontab定时任务(每分钟启动一次)来发送邮件,都需要考虑什么情况呢php互斥插件

定时任务执行超时

crontab定时任务设为每分钟启动一次,如下:

* * * * * php /root/php/cron.php

问题:如果这脚本出现异常,进程僵死怎么办?

假设由于未知因素,cron.php 脚本一直执行,没有退出。极端情况,进入一个死循环。原来说好的一分钟执行一次,现在后面的脚本也不能跑了。

解决办法:使用timeout设置脚本执行超时时间

* * * * * timeout 120 php /root/php/cron.php >> /root/php/logs.log 2>&1

上面定时任务脚本最大执行时间120秒,超过120秒之后进程就会退出,这样就可以解决僵死的情况。

php互斥插件_php插件开发

定时任务进程互斥

问题:由于设置的定时任务是每分钟启动一次,在未来的某个时刻就会出现多个脚本进程在执行相同任务,此刻可能就会造成数据的不一致性等问题。那么,该怎么避免呢?

解决办法:使用 flock 设置文件锁来进行互斥控制。

php互斥插件_php插件开发

用法:flock [选项] <文件|目录> <命令> [<参数>...]flock [选项] <文件|目录> -c <命令>flock [选项] <文件描述符号码>参数选项: -s, --shared 获取共享锁 -x, --exclusive 获取排他锁(默认) -u, --unlock 移除锁 -n, --nonblock 被其他服务锁住的时候返回失败而非等待 -w, --timeout <秒> 等待限定的时间 -E, --conflict-exit-code <数字> 冲突或超时后的退出代码 -o, --close 运行命令前关闭文件描述符 -c, --command <命令> 通过 shell 运行单个命令字符串 -F, --no-fork 执行命令时不 fork --verbose 增加详尽程度 -h, --help display this help -V, --version display version

文件锁互斥参数为 flock -xn, 同时设置互斥文件 /tmp/cron1.lock。

* * * * * flock -xn /tmp/cron1.lock -c "timeout 120 php /root/php/cron.php"

为了方便排查,把输出数据追加到指定日志文件中。

* * * * * flock -xn /tmp/cron1.lock -c "timeout 120 php /root/php/cron.php >> /root/php/logs.log 2>&1"定时任务执行频率提升

问题:觉得一分钟启动一次频率太低,想10s启动一次怎么办?

解决办法:添加多个相同定时任务,每个定时任务sleep指定时间之后执行。

* * * * * php /home/app/email.php >> /home/log/test.log 2>&1* * * * * ( sleep 10 ; php /root/php/cron.php >> /root/php/logs.log 2>&1 )* * * * * ( sleep 20 ; php /root/php/cron.php >> /root/php/logs.log 2>&1 )* * * * * ( sleep 30 ; php /root/php/cron.php >> /root/php/logs.log 2>&1 )* * * * * ( sleep 40 ; php /root/php/cron.php >> /root/php/logs.log 2>&1 )* * * * * ( sleep 50 ; php /root/php/cron.php >> /root/php/logs.log 2>&1 )定时任务互斥及超时验证

用于测试的php脚本

<?php$i = 10000;while ($i > 0) { echo --$i . \PHP_EOL; sleep(1);}

添加crontab定时任务

* * * * * flock -xn /tmp/cron1.lock -c "timeout 120 php /root/php/cron.php >> /root/php/logs.log 2>&1"

查看日志文件/root/php/logs.log发现会有数值不停输出,120秒左右之后数值暂停输出。此时使用ps -aux | grep php查看没有发现定时任务相关的进程信息,说明timeout 120起到了作用。然后,等待若干秒,等下一分钟的第一秒到达时,会发现数值又开始输出,也可以看到对应的定时任务进程信息,如此往复。

99999998999799969995....

定时任务执行期间,若再打开另外一个终端,手动在命令行执行:

flock -xn /tmp/cron1.lock -c "timeout 120 php /root/php/cron.php >> /root/php/logs.log 2>&1"

结果:① 命令行执行命令由于没有获得锁,直接退出(因为 flock 互斥)② 定时任务执行120 秒后自动由于超时退出进程(因为 timeout 120),此时再手动在命令行执行则可以成功

发布于 2024-08-25 15:08:54
收藏
分享
海报
0 条评论
60
目录

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~