Contents
前言
这篇文章是2014年7月对OpenStack RPC问题的总结,因为去年给py-amqp提交的keepalive patch[1]终于被引起重视并merged了 ,所以把笔记公布出来,希望对OpenStacker有所帮助。目前来看,文章所说的问题和方法还没过时。
问题分类
我们使用OpenStack RPC(RabbitMQ)会遇到的多种故障, 社区对这些问题也一直是修修补补,详见 https://bugs.launchpad.net/mos/+bug/856764 。
消息持久性
通过设置各个openstack服务的配置文件和rabbitmq的policy来解决。
RabbitMQ高可用
两种解决办法:
- Haproxy + Rabbitmq集群 + Mirror Queue
- conf.rabbit_hosts + Rabbimq集群 + Mirror Queue
Socket Close
由于一台rabbitmq服务器宕机了,导致连接这台服务器的consumer无法接收到消息,consumer无法觉察到这个idle connection已经被terminated,所以consumer不会重连(即时RabbitMQ服务器已经重启)。则会导致nova-scheduler,nova-compute,cinder-scheduler,cinder-volume,neturon agent无法正常工作。
社区目前的解决办法是:在oslo.messaging,使用heartbeat check线程不断向RabbitMQ发送heartbeat消息,检查connection是否中断。最后的实现版本是 https://review.openstack.org/#/c/146047/ 。
在去年的时候,heartbeat check方法没有被merged到oslo.messaging里面,而且我们觉得这个方法把问题弄复杂了,因此使用了一个简单的方法,详见下文。
Consumer Cancel Notifications (CNNs)
当一个queue的slave被提升为master时(旧的master宕机了,导致rabbitmq集群重新选举),它会向它所连接的所有consumer发送CNN消息,但是不会关闭connections,这导致consumer再也收不到消息了,除非重连。社区的解决办法是:在oslo.messaging,增加channel_error异常处理:https://review.openstack.org/#/c/77276/
Kombu Reconnect Hang
当rabbitmq在选举的时候,client发起连接,rabbitmq不会相响应它的请求,导致client一直处于等待状态。社区的解决办法是:在client重连之前,先迟延1秒钟,等待rabbitmq选举结束之后再重连。
https://review.openstack.org/#/c/76686/
更简单的办法
针对于Socket Close, 我们有更简单的解决办法,只需要给kombu pyamqp transport增加简单的keepalive参数,而不需要实现heartbeat check线程。我们的方法需要修改py-amqp和oslo.messaging 。
OpenStack RPC的调用链是 nova -> rpc -> oslo.messaging -> kombu -> pyamqp(or others)
修改oslo.messaging,增加了几个参数 https://github.com/zhurongze/oslo.messaging/commit/71c3380c4c411eed261ab0a4741931d07d5c44c7
oslo.messaging会强制kombu使用 pyamqp transport,并把keepalive options通过kombu传给 pyamqp transport。
在kombu的代码中 https://github.com/celery/kombu/blob/master/kombu/transport/__init__.py 可以看到
在 https://github.com/celery/kombu/blob/master/kombu/transport/pyamqp.py 中 import 了 amqp 模块。在CentOS 6.5中 amqp 模块对应的代码是py-amqplib,目前已经不维护了。在Ubuntu 14.04 中的 amqp 模块对应的代码是 py-amqp,目前是由celery团队维护的。kombu模块也是celery团队维护的。
我们在py-amqp增加keepalive参数[1],使得默认tcp keepalive检查时间由7200秒(Linux默认值)变为30秒(可设置),这样就能快速检测除已经被terminated的connection。
假如你没有指定transport类型,而且host支持librabbitmq,kombu会默认使用 librabbitmq作为transport。
[1] https://github.com/celery/py-amqp/commit/b9a6601a93927449fa6f524750e3842cc5c181bd
大神,跪谢啊~
Pingback: OpenStack年底总结 | 陈沙克日志
这个是针对oslo.messaging 1.8+做的fix,有针对openstack juno, oslo.messaging 1.4.1的fix么?
通用的呀,你可以自己backport。
librabbitmq 支持keepalive或者hearbeat吗 ?
没用过librabbitmq,需要你自己查了。
学习了,openstack的RabbitMQ可以尝试做集群部署
为啥不直接调整系统的keepalive参数?
这样就会影响这个系统了,系统上还会跑其他服务和应用。
大神,你好
上面说的集中方法 都是针对 “Haproxy + Rabbitmq集群 + Mirror Queue” 这种HA而言的对吧?