oslo_messaging踩坑小记

来源:互联网 发布:ichartjs python 编辑:程序博客网 时间:2024/04/29 17:56

最近在做一个分布式的任务系统,借鉴了OpenStack的思想,使用rabbitmq来做消息中间件,便于扩展。

本着不重复造乱子的理念,哈哈,我也用oslo.messaging将worker做成RpcServer来提供服务。在本地写好简单的Demo后,测试了一下运行无误。上传到部署了OpenStack的服务器后,使用rpcapi发布任务,结果core dump了,悲催,使用gdb查看core file,发现是librabbitmq1使用了无效的内存引用或者发生段错误造成的。oslo_messaging只是对多种transport做了进一步封装,底层也是用到了kombu这个AMQP库,当transport是amqp时,kombu会进行环境监测判断是否安装了librabbitmq,如果安装了就使用librabbitmq,没有则使用pyamqp;因为librabbitmq是使用C编写的库,所以比pyamqp速度快很多。因为我的系统装了librabbitmq,所以在调用的时候,发生了这个错误,网上查了下有很多人也遇到这个问题了,据说是1.0.3版本的python-librabbitmq的bug导致的。

Segmentation fault (core dumped)

(gdb) core-file corewarning: core file may not match specified executable file.[New LWP 14363][Thread debugging using libthread_db enabled]Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".Core was generated by `python test.py'.Program terminated with signal SIGSEGV, Segmentation fault.#0  0x00007f1e8a4d46ab in amqp_pool_alloc () from /usr/lib/x86_64-linux-gnu/librabbitmq.so.1
但是OpenStack居然能正常运行,通过debug发现,OpenStack服务通过oslo_messaging创建的kombu connection居然是pyamqp的,也就是没有使用librabbitmq,这点真的很奇怪,因为通过创建的参数来看,OpenStack也没指明让kombu使用pyamqp,百思不得其解啊。后面经过验证,发现是eventlet的monkey_patch导致kombu检测不到librabbitmq,最后才使用的pyamqp。至于eventlet的monkey_patch是如何让kombu检测不到librabbitmq的,还需进一步验证。

卸载librabbitmq可以解决问题,但是我有20台OpenStack的计算节点都装了librabbitmq,另外我担心破坏已有的环境,所以我想着能否让kombu检测不到librabbitmq了,这样就不会使用它了。看kombu的源代码,里面检测librabbitmq的代码很简单,导入一次,如果没有异常,就说明可以使用:

def supports_librabbitmq():    if _detect_environment() == 'default':        try:            import librabbitmq  # noqa        except ImportError:  # pragma: no cover            pass        else:                # pragma: no cover            return True

这个时候我想到了eventlet的monkey_patch,就是在运行时打patch来修改已有的代码,这点在Python上实在是很方便。于是,我也在我的代码运行之初检测librabbitmq是否存在,如果不存在,就不用管了;存在就判断版本,如果是1.0.3,那么就‘’删除‘’掉这个模块,这样在接下来运行的代码中有导入librabbitmq的地方都会报ImportError异常,迫使kombu不会是使用到有bug的python-librabbitmq版本

#!/usr/bin/python2.7import systry:    import librabbitmqexcept Exception:    passelse:    version = getattr(librabbitmq, '__version__', None)    if version == '1.0.3':        sys.modules['librabbitmq'] = None




原创粉丝点击