如何使用 RabbitMQ 重新加载 CodeIgniter 中的代码更改?

How to reload code changes in CodeIgniter with RabbitMQ?

我将 CodeIgniter 框架与 RabbitMQ 一起用于执行耗时的活动,例如发送电子邮件、生成 PDF。

每当我更改 PHP 文件中的代码时,比如库或控制器,直到我重新启动 Apache,RabbitMQ 才会执行旧代码。如何解决?

控制器中的函数,

public function receive()
{
    $this->db->reconnect();
    $connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
    $channel = $connection->channel();
    $channel->queue_declare('generate_pdf', false, false, false, false);
    echo "[*] Started listening to connections... To exit press CTRL+C\n";
    $generate_pdf = function ($data)
    {
        $this->generatepdf->generate($data); // Generatepdf.php library -> generate() function
    };
    $channel->basic_qos(null, 1, null);
    $channel->basic_consume('generate_pdf', '', false, true, false, false, $generate_pdf)

    while ($channel->is_consuming())
    {
        $channel->wait();
    }
}

从终端开始,

php index.php Controllerfile.php receive

正如预期的那样工作正常。所以当一个job被push到队列中时,库文件Generatepdf.php中的generate()函数被调用,执行完成。

但是,如果我通过编辑器修改 generate() 函数,或者我重新上传包含更改的文件,这些更改在我重新启动 Apache 服务器之前不会反映出来。

更改前的函数定义:

public function generate()
{
    echo "Hello the data is 250";
}

输出:你好数据是250

更改后的函数定义:

public function generate()
{
    echo "Hello the data is 251";
}

重启Apache前的输出:你好数据是250

重启Apache后的输出:你好数据是251

为什么会这样?如何执行以刷新文件中的更改?

您显示的代码包含此循环:

while ($channel->is_consuming())
{
    $channel->wait();
}

意思是“除非与 RabbitMQ 的连接中断,否则等待新消息,处理它,然后再次等待,直到永远”。换句话说,这是一个无限循环,PHP进程运行除非你杀死它,否则它不会退出。

与我看到的一些描述相反,PHP 是一种 编译语言 ,而不是解释语言:当 PHP 进程被要求加载一个 PHP 代码文件,它 看一次 ,将其编译为 machine-friendly 表示(称为“操作代码”),然后不需要再次查看它以多次执行其中的代码。因此,当您编辑文件时,已经 运行 的进程不会注意到,也不会编译您的新代码。

如果你想加载新的代码,你需要退出死循环,所以这个过程结束,然后开始一个新的,它会编译你的新代码。例如,您可以检查特定文件的循环,测量它已经 运行 的时间,或者监听告诉它退出的特殊消息。然后,您可以使用“supervisord”之类的东西来确保脚本在退出时 re-run,或者只是有一个“cron”任务来定期启动一个新副本。

另外一点:PHP 有一个称为“OpCache”的功能,它甚至在进程之间重用文件的编译版本,以获得更好的性能。默认情况下,它会查看文件的时间戳来决定是否重新编译它,因此如果您编辑文件,它会“发出通知”,但可以关闭该检查以获得最佳性能。如果那是问题所在,您会在 all PHP 代码中看到它,而不仅仅是您的 RabbitMQ 循环。