代码方式实现PHP服务定时拉取

23. 五月 2019 PHP 0

定时拉取是一种很常见的操作,比如需要定时从配置中心拉取一下配置,或者同步一下状态等。这对于编译型语言来说十分简单,只需要开一个独立的线程,拉一下、sleep一会就好了。但是对于无状态的PHP服务,比如wordpress,或者一些API层的服务,由于他们没有常驻进程,想跑定时任务就比较麻烦了(swoole的除外,我们只讨论fpm的)。

其实搞定时任务的方式有挺多,比如起一个cron脚本,定时拉(配置或者什么)写到一个文件里,php每次读这个文件结果。这么搞是最简单的,但是当你维护的是一个几百台docker的集群的时候,这么搞运维可能会骂死你;如果是用git的webhook部署的话,如果改了脚本逻辑得手动上去改一下……我就是遇到了一个类似的复杂情况,不得已用了这种方法。留着以后当个面试题也是极好的。

这种方式需要几个小部分来配合:

  1. xxx.lock 文件锁,里面存有一个timestamp,表示更新时间。
  2. xxx.conf 拉取到的配置(或其他什么东西,存在里面)。
  3. lock.sh 脚本,用户检查锁
  4. sync.sh 脚本,用于执行拉取操作
  5. xxx.php php文件

他们之间相互的关系大概是这样:

xxx.php及钩子

xxx.php主要任务有两个:

  1. 从lockfile读一下时间,看需不需要启动任务
  2. 如果需要,启动lock脚本

注意updateConfHook这个函数,他首先会尝试从lockfile把更新时间读出来,读之前会使用flock对文件加锁,如果成功,并且当前时间距离上次更新时间超过1分钟,那么我们解锁lockfile并启动lock.sh,后面的事就不用管了。

当然了,还需要哪里触发一下这个函数,不妨把钩子写成一个middleware,对代码侵入性较小。flock这里使用的目的是保证只有一个脚本存在,且尽可能不影响php性能。

lock.sh

lock.sh尝试对文件上锁,如果成功则进行下一步,失败则说明有其他脚本在跑,自己退出就好。

sync.sh

首先拉取配置,或者做你想做的事,然后保存、检查。如果合法则替换,并把更新日期写入lock文件。因为sync.sh是被lock.sh调用的,sync.sh不退出,文件锁就不会释放,所以这里sleep 60秒是为了避免其他脚本被启动,毕竟1分钟内不需要更新。

PS:虽然xxx.lock是在锁死状态,但是并不妨碍它被修改,大家可以试下。

流程图


发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据