1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| 两者都可以用于处理消息队列中的任务 区别在于:
1. 执行原理不同 work 命令是单进程的处理模式。 按照是否设置了 --daemon 参数,work命令又可分为单次执行和循环执行两种模式。 - 单次执行:不添加 --daemon参数,该模式下,work进程在处理完下一个消息后直接结束当前进程。当队列为空时,会sleep一段时间然后退出。 - 循环执行:添加了 --daemon参数,该模式下,work进程会循环地处理队列中的消息,直到内存超出参数配置才结束进程。当队列为空时,会在每次循环中sleep一段时间。 listen 命令是 双进程 + 管道 的处理模式。 listen命令所在的进程会循环地创建 单次执行模式的 work 进程,每次创建的 work 进程只消费一个消息就会结束, 然后 listen 进程再创建一个新的 work 进程, - listen 进程会定时检查当前的 work 进程执行时间是否超过了 --timeout 参数的值, 如果已超时, 则 listen 进程会 kill 掉 work 进程, 然后抛出异常 - listen 进程会通过管道来监听当前的 work 进程的输出, 当 work 进程有输出时, listen 进程会将输出写入到 stdout / stderr - listen 进程会定时通过 proc_get_status() 来监控当前的 work 进程是否仍在运行, work 进程消费完一个任务之后, work 进程就结束了,其状态会变成 terminated, 此时 listen 进程就会重新创建一个新的 work 进程并对其计时, 新的 work 进程开始消费下一个任务
2.结束时机不同 - work 命令的结束时机在上面的执行原理部分已叙述,此处不再重复 - listen 命令中,listen 进程和 work 进程会在以下情况下结束: - listen 进程会定时检查当前的 work 进程的执行时间是否超过了 --timeout 参数的值,如果已超时, 此时 listen 进程会先 kill 掉当前的 work 进程, 然后抛出一个 ProcessTimeoutException 异常并结束 listen 进程 - listen 进程会定时检查自身使用的内存是否超过了 --memory 参数的值,如果已超过, 此时 listen 进程会直接 die 掉, work 进程也会自动结束.
3.性能不同 - work 命令是在脚本内部做循环,框架脚本在命令执行的初期就已加载完毕; - 而listen模式则是处理完一个任务之后新开一个work进程,此时会重新加载框架脚本。 因此: work 模式的性能会比listen模式高。 注意:当代码有更新时,work 模式下需要手动去执行 php think queue:restart 命令重启队列来使改动生效;而listen 模式会自动生效,无需其他操作。
4.超时控制能力 - work 模式本质上既不能控制进程自身的运行时间,也无法限制执行中的任务的执行时间。 举例来说,假如你在某次上线之后,在上文中的 \application\index\job\Hello.php 消费者的fire方法中添加了一段死循环 : public function fire(){ while(true){ //死循环 $consoleOutPut->writeln("<info>I am looping forever inside a job.</info> \n"); sleep(1); } } 那么这个循环将永远不能停止,直到任务所在的进程超过内存限制或者由管理员手动结束。这个过程不会有任何的告警。更严重的是,如果你配置了expire ,那么这个死循环的任务可能会污染到同样处理 helloJobQueue 队列的其他work进程,最后好几个work进程将被卡死在这段死循环中。详情后文会说明。 work 模式下的超时控制能力,实际上应该理解为 多个work 进程配合下的过期任务重发能力。 - 而 listen 命令可以限制 listen 进程创建的 work 进程的最大执行时间。 listen 命令可通过 --timeout 参数限制 work 进程允许运行的最长时间,超过该时间限制后, work 进程会被强制 kill 掉, listen 进程本身也会抛出异常并结束; - 这里有必要补充一下 expire 和 timeout 之间的区别: - expire 在配置文件中设置,timeout 在 listen命令 的命令行参数中设置,而且,expire 和 timeout 是两个不同层次上的概念: - expire 是指任务的过期时间。这个时间是全局的,影响到所有的work进程。(不管是独立的work命令还是 listen 模式下创建的的 work 进程) 。expire 针对的对象是 任务。 - timeout 是指 work 进程的超时时间。这个时间只对当前执行的 listen 命令有效。timeout 针对的对象是 work 进程。
5.使用场景不同 根据上面的介绍,可以看到, work 命令的适用场景是: - 任务数量较多 - 性能要求较高 - 任务的执行时间较短 - 消费者类中不存在死循环,sleep() ,exit() ,die() 等容易导致bug的逻辑 listen命令的适用场景是: - 任务数量较少 - 任务的执行时间较长(如生成大型的excel报表等), - 任务的执行时间需要有严格限制
|