请问PHP如何实现“代码热更新”

是这样,我有一个PHP脚本,不断地从队列里取出任务予以处理,大致逻辑:
<main.php>
require do_job.php;
while (true)
{
$job = queue_pop(); // 取出一个任务,阻塞调用
do_job($job); // 这个函数来自 do_job.php
}

该脚本直接从命令行启动:
nohup php main.php &

但是随着业务的发展,我发现要处理的任务种类越来越多,所以我需要不断地修改 do_job() 函数,以处理新类型的任务或更改之前的逻辑;但是每次修改这个函数,我都需要先 kill 掉之前的进程,然后再次执行上面的命令行,非常不方便。

我想问,如何在不停止 main.php 进程的条件下,更新 do_job.php ?如果可以的话,尽量不要引入重量级的第三方框架。

我知道有一种方案可行,就是每当收到任务后,创建一个php子进程,把任务通过某种进程间通信机制传给它来处理,就像Apache服务器。但是我觉得这种方案过于重量级了,因为多数情况下 do_job()函数很简单,很快就能执行完,专门为它创建一个进程,有点“杀鸡用牛刀”。

谢谢!

阅读 6.8k
5 个回答

可以用 inotifywait来监视文件的修改, 发现修改时, kill 原来的进程并开启新进程

安装 inotify-tools

apt install inotify-tools

写监控脚本

存为 watch.sh

#!/bin/sh

#响应 Ctrl+C
sigint_handler()
{
  kill $PID
  exit
}

trap sigint_handler SIGINT

while true; do
  $@ &
  PID=$!
  inotifywait -e modify -e move -e create -e delete -e attrib -r $2
  kill $PID
done

print.php 测试文件

<?php
$count=0;
function queue_pop(){
    return $count++;
}

function do_job($job){
 echo 'do '.$job;
}


while (true)
{
$job = queue_pop(); // 取出一个任务,阻塞调用
do_job($job); // 这个函数来自 do_job.php
sleep(1);
}

运行监控脚本

./watch.sh php print.php 

我们业务中也有类似这样的异步任务模块,用于处理队列、报表统计等等

  • crontab 任务,每分钟执行一个 crontab.sh 脚本,crontab.sh 脚本用于分发 php 任务,可自定义设置1分钟、5分钟、1小时,根据需要分配粒度,这样新增 php 任务不需要运维帮忙新增 crontab 任务(需要申请运维工单)
  • php 任务激活之后,执行任务前:判断是否存在任务、执行任务进程数是否超过规定数目、进程是否触发概率回收
  • 执行当前任务

简单实用 while + nohup 方式, 使 php 脚本常驻,逻辑处理不当,容易导致内存泄漏

写个脚本 检测你代码是否变化 变化就重启

不建议 在php代码中 写死循环, 最好是隔一段时间 退出脚本 释放内存 而且php脚本经常修改 无法运行最新的php代码 可以使用shell脚本 写死循环 没秒钟监听php脚本是否执行了,如果没有执行 就启动脚本

1 do job 本身 可以非常简单,只是读取配置,然后通过 http / shell 开启进程处理
代码本身可以不涉及业务,所以也就没有啥 热更新的讲法

2 用 crontab 每分钟执行 do job,do job 记录启动时 时:分,超过启动时的 时:分 就自动退出,crontab 会启动下一分钟新 do job 的执行,这样的话 热更新 最多延迟 1分钟

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题