PHP消息队列业务解耦实践
php是web开发的利器,在中小型web开发中,无人能撼动其地位。不过在大型应用中,对比java,python,由于相应生态的缺乏,在构建大型web服务的时候,经常会显得力不从心。
其中缺乏完善的消息中间件,是一个较大问题。
php作为一门偏web开发的语言,一般跑在apache,fastcgi上面,生存期从请求开始到结束,这就决定了他不太适合跑长时间运行的服务,假如需要跑一些例如发送邮件,统计分析,后计费类的业务,一般都是用crontab来定时请求。php的哲学是实用主义,够用就行,crontab在大多数情况下都能满足需求,简单的的后端处理需求,直接用crontab等解决就行,不用多想。
但是在大型web服务中,crontab就开始满足不了了,需要更高精度的业务控制,需要更高性能的异步业务处理。一般的解决方式是通过消息队列,将任务发送到后端应用中处理。前端负责从mysql,redis等取数据,展示。后端负责处理耗时较长,不需要立即返回的任务。而怎样消费消息队列,不用局限于php,python、golang、java等也可以去消费消息队列的任务,这样就实现了服务的解耦合。
php的消息队列,之前用过php-resque,这是基于redis的一款消息队列服务,phpresque被用的比较多,我们用起来也比较稳定,没出过大的坑,大多数情况下,都能很好的满足需求。后来随着业务的发展,我们把消息队列换成了nsq,原因是:
- 单点故障:
虽然出问题的时候,非常少,但是因为没有很好的多节点机制,一旦出问题,整个系统都会挂掉,不能很快的切到备用节点。
- 性能
后端消费者限定了php,在性能上面有一些慢。
- 部署
部署上依赖的东西有点多,需要安装与维护redis,php拓展,配置上有点复杂
- 拓展
消费者限定php,一些情况下,我们想用golang来处理对性能有要求的业务
nsq是一款非常优秀的消息队列服务,部署很简单,启动程序即可,无依赖,消费消息有python golang的sdk,我们想把对性能要求比较高的业务处理换成golang,所以就把消息服务替换成了nsq。目前我们的结构是这样的:
前端是web服务器组,直接处理的数据是mysql,memcache,以及通过nsq往后端发送任务数据。
后端包括抽象的微服务,以及各种业务后处理。消息处理完成之后,结果一般会进入mysql数据库,供前端业务进行消费。