php消费队列引起的问题

总哈哈 2016-12-28 11:22:56
大概问题是这样的, 有一个redis队列,里面存放着需要消费的消息, 这里起一个 php进程 消费

1. 后端起了一个php进程,while(true)循环的那种
2. 不停的从Redis对列读消息
2. 读到消息就消费掉

问题来了, 由于里面涉及到的消费代码(会动态的调用类,方法之类),当代码(项目代码)改了以后,需要重启队列队列才会适应最新的代码(不重启会有一些莫名其妙的问题出现,你懂的),那么有什么好的方法解决这类问题呢?
如果是大型的企业,每次代码更新估计不是重启这个php进程吧?

还请高手指导一下,一直在想这个问题,想到了几个,可能可行,没有实践过,但是想知道有没有更好的
1. 使用php创建一个新的进程来处理新的消息
2. 使用python读取队列,动态调用php cli命令执行

知道的,不知道的都可以进来讨论一下,欢迎高手
...全文
496 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
总哈哈 2017-01-16
  • 打赏
  • 举报
回复
感谢大家的回复,还是没有解决问题! 结帖
傲雪星枫 2017-01-02
  • 打赏
  • 举报
回复
可以加一个参数,如果是0,才出队处理,否则不出队处理。 重启时,先把这个参数设置为1。然后等当前任务处理完成了,再重启动。 之后把这个参数改为0。
没有风筝的线 2017-01-01
  • 打赏
  • 举报
回复
classkit_import 我觉得可以在循环里判断文件的修改时间, 如果修改时间不一样就重新载入这个类. 然后下面的代码就会更新, 没试过不知道有没有可行性
没有风筝的线 2017-01-01
  • 打赏
  • 举报
回复
刚才在手册上看到这个函数 classkit_import () classkit_import — Import new class method definitions from a file //classkit_import导入新课的方法定义一个文件
<?php
// file: newclass.php
class Example {
    function foo() {
        return "bar!\n";
    }
}
?> 

<?php
// requires newclass.php (see above)
class Example {
    function foo() {
        return "foo!\n";
    }
}

$e = new Example();

// output original
echo $e->foo();

// import replacement method
classkit_import('newclass.php');

// output imported
echo $e->foo();

?> 
 
以上例程会输出:

foo!
bar!
xuzuning 2016-12-29
  • 打赏
  • 举报
回复
class XXLog { function OriginalWriteArray(....) { include 'code.php'; } 动态修改 code.php 中的代码,是不会需要重启的
总哈哈 2016-12-29
  • 打赏
  • 举报
回复
我还是贴一下我的部分代码吧, 可以确定是有我前面说的那个问题的

        while (true) {
            $messageBody = $cacheHandle->brpop(array(
                XXQueue::QUEUE_KEY_LEAVE1,
                XXQueue::QUEUE_KEY_LEAVE2,
                XXQueue::QUEUE_KEY_LEAVE3
                ), 0);

            list($key, $value) = $messageBody;
            $jsonContent = json_decode($value, true);

            $className = $jsonContent['class'];
            $params = $jsonContent['params'];

            // 固定在某个命名空间下面
            $classInstance = 'Api\\Queue\\' . $className;
            XXLog::OriginalWriteArray("queue_message", [
                'time' => date('Y-m-d H:i:s'),
                'class_name' => $classInstance,
                'value' => $value,
                'result' => 'begin'
            ]);
            if (!class_exists($classInstance)) {
                continue;
            }

            try {
                $newClass = new $classInstance();
                if (!$newClass instanceof Queue\IQueue) {
                    XXLog::OriginalWriteString("queue_message", "$newClass not implements Queue\\IQueue!");
                    continue;
                }
                $newClass->run($params);
......
xuzuning 2016-12-29
  • 打赏
  • 举报
回复
你 include 的是方法体的代码,就不会有什么问题 不过这样的话,代码会变得很难看(调试也会有一定的难度) 不过 Redis 中保存的是数据,跟代码有什么关系
总哈哈 2016-12-29
  • 打赏
  • 举报
回复
我希望达到什么效果呢? 就好像一个shell,一直读取redis内容,如果读到就执行 php index.php cli/redisQuery 一次,但是这样的方法不好。
总哈哈 2016-12-29
  • 打赏
  • 举报
回复
这只是一个比如,我想表达的是 while里面一直从redis里面读取内容,我用到了TP框架,这里不可能把代码都贴出来 while(1) { 1. 从redis里面读取数据 (后台会时不时的往Redis队列里面塞数据) 2. 动态加载类且执行里面的方法 (我要问的是,可能中间被执行过的类->方法里面的东西被改过了),这个时候就不能执行最新的代码 } 这里我的调用方式是 nohup php index.php cli/redisQuery & 这样被加载过类改变以后,我必须杀掉以后再重新执行上面的命令
引用 4 楼 xuzuning 的回复:
你连语法都不顾? 类定义文件重复加载不就报错了吗? 动态加载的只能是方法体
xuzuning 2016-12-28
  • 打赏
  • 举报
回复
你连语法都不顾? 类定义文件重复加载不就报错了吗? 动态加载的只能是方法体
总哈哈 2016-12-28
  • 打赏
  • 举报
回复
A.php

 include "B.php";

 while (true) {
	$aa = new AAA();
	$aa->BBB();

	sleep(5);
 }

B.php

class AAA {
 
	public function BBB() {
	
		echo "AAA!!!!11111111111111111111111111";
                // 在cli模式下面运行A.php以后,改echo后面的内容,是没有用的
	}
 }
总哈哈 2016-12-28
  • 打赏
  • 举报
回复
好像不是这样的,我的想法是这样的,分两个页面 A.php

while(true){
    if (从Redis里面读取内容 class.function) {
              include class 所在的文件
              $aa  = new classA();
              $aa->functionA();
    } 

}
B.php

public class ABC {

        public function functionA() {
                //  1. 在控制台cli模式下面执行A.php
                //  2. 修改这里的内容,会发现修改的内容不会反映到while里面
        }
}
目前只有重启才可以解决这个问题,我希望解决这个问题,看有没有比较好的方法
引用 1 楼 xuzuning 的回复:
你的两个备选方案与重启有什么区别? 只要你不是直接修改 while(true)循环 中的代码,而是 include 工作代码的话,就没必要重新启动队列 php 是弱类型语言,即便队列元素的数据结构发生变化了,只要你能在处理程序中正确识别。一样是不需要重启的
xuzuning 2016-12-28
  • 打赏
  • 举报
回复
你的两个备选方案与重启有什么区别? 只要你不是直接修改 while(true)循环 中的代码,而是 include 工作代码的话,就没必要重新启动队列 php 是弱类型语言,即便队列元素的数据结构发生变化了,只要你能在处理程序中正确识别。一样是不需要重启的

21,893

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧