Jos*_*son 9 php asynchronous message-queue gearman task-queue
考虑一个PHP Web应用程序,其目的是接受用户启动通用异步作业的请求,然后创建一个工作进程/线程来运行该作业.作业不是特别占用CPU或内存,但预计会经常阻塞I/O调用.每秒应该启动不超过一个或两个作业,但由于运行时间长,可能会同时运行许多作业.
因此,工作并行运行至关重要.此外,每个作业都必须由负责杀死挂起的工作人员,根据用户请求中止工作人员等的经理守护程序进行监控.
实现这样的系统的最佳方法是什么?我可以看到:
好吧,如果你在Linux上,你可以pcntl_fork
用来分叉孩子.然后"主人"看着孩子们.每个孩子完成任务然后正常存在.
就个人而言,在我的实现中,我从来不需要消息队列.我只是在"master"中使用带锁的数组.当一个孩子找到工作时,它会写一个带有工作ID号的锁文件.然后主人会等到那个孩子退出.如果在退出子项后锁定文件仍然存在,那么我知道任务未完成,并重新启动具有相同作业的子项(删除锁定文件后).根据您的具体情况,您可以在简单的数据库表中实现队列.在表中插入作业,并每隔30或60秒检查主表中的表以获取新作业.然后只有在子项完成后才从表中删除它们(并且子项删除了锁定文件).如果您一次运行多个"主",则会出现问题,但您可以实现全局"
我不建议使用FastCGI.它可能会导致一些非常模糊的问题,因为环境要坚持下去.相反,如果您必须拥有Web界面,请使用CGI,但理想情况下使用CLI应用程序(deamon).要从其他进程与主服务器连接,您可以使用套接字进行TCP通信,也可以创建FIFO文件进行通信.
至于检测挂起的工作人员,你可以实现一个"心跳"系统,孩子SIG_USR1
每隔很多秒就会向主进程发出一个问题.然后,如果你没有在两三次听到孩子的声音,它可能会被挂起.但问题是因为PHP不是多线程的,你无法判断一个孩子是挂起还是只是在等待阻塞资源(比如数据库调用)......至于实现"心跳" ,你可以使用一个滴答功能来自动节拍(但请记住,阻止调用仍然不会执行)...