【ActiveMQ学习】Python语言整合ActiveMQ(时遇到的那些坑)

自己的一个项目里用到Python和Java的通讯,不准备使用Jpype来调用Java类方法的方式来做,于是想到了消息队列。

经过对各种消息队列的比对最终选定了ActiveMQ。RabbitMQ、ZeroMQ、ActiveMQ介绍: http://blog.csdn.net/chszs/article/details/8479072

首先准备需要的环境:

ActiveMQ 5.10.0 Release、Python 2.7、stomp 0.2.9

python连接ActiveMQ的方式官方examples有stomp、amqp这两种方式的例子。stomp协议在python有很多实现模块,本文使用的是stompy。

stompy地址: https://pypi.python.org/pypi/stompy

stompy文档: https://pythonhosted.org/stompy

一、环境准备工作

解压ActiveMQ到任意目录,然后在命令行里执行{activemq目录}\bin\activemq.bat start(注意:不知道是不是我选用高版本的缘故,此处如果按网上其他教程直接activemq.bat不加start参数启动的话不能正常启动)

【ActiveMQ学习】Python语言整合ActiveMQ(时遇到的那些坑)_第1张图片

图:直接执行activemq.bat未加start参数,启动出错

【ActiveMQ学习】Python语言整合ActiveMQ(时遇到的那些坑)_第2张图片

图:执行activemq.bat start,启动成功

安装Python,请看Python安装教程 本文不赘述。

接下来编译安装Python的stomp模块:

将stomp解压到非中文路径下,切换命令行工作目录到解压后的stomp目录下,执行python setup.py install命令。注意:安装python模块可能需要C++编译器,作者机器上已经安装了VS2008。stomp模块的安装需要提前以安装setuptools工具

【ActiveMQ学习】Python语言整合ActiveMQ(时遇到的那些坑)_第3张图片

图:stomp模块安装成功

二、代码

根据stomp官方文档的教程https://pythonhosted.org/stompy/reference/stompy.simple.html 编写代码之后,执行会有问题。

官方代码:

from stompy.simple import Client
# 官方的例子使用的Client(),默认值hostname=localhost,port=61613.因为作者的ActiveMQ服务器与程序不在一台机器所以做了下面的修改。
stomp = Client('192.168.1.166', 61613)
stomp.connect() stomp.put("The quick brown fox...", destination="/queue/test")
stomp.subscribe("/queue/test")
message = stomp.get_nowait()
message.body
'The quick brown fox...'
stomp.ack(message)
stomp.unsubscribe("/queue/test")
stomp.disconnect()
执行这段程序出现了如下错误:

【ActiveMQ学习】Python语言整合ActiveMQ(时遇到的那些坑)_第4张图片

错误提示在执行stomp.get_nowait();方法时得到的是空回复。此时说明,stomp连接ActiveMQ服务器是成功的,并且stomp.put()方法成功将消息推送到了ActiveMQ服务器。但stomp向服务器订阅信息时发生错误。

根据stomp官方文档的说明,对stomp.get_nowait()方法的解释为:Remove and return an item from the queue without blocking. Only get an item if one is immediately available. Otherwise raise the Empty exception。(如果ActiveMQ服务器有消息存在,则获取消息,如果方法调用时ActiveMQ服务器没有可用消息就会抛出异常。)stomp.get_nowait()方法之前虽然执行了stomp.put()方法向ActiveMQ服务器发送了消息,但可能因为延迟的缘故导致stomp.get_nowait()方法执行时ActiveMQ服务器还没有可用消息导致错误发生

解决办法:

方法一,在stomp.put()执行之后,stomp.get_nowait()执行之前添加代码time.sleep(0.1)让程序短暂休眠。

【ActiveMQ学习】Python语言整合ActiveMQ(时遇到的那些坑)_第5张图片

方法二,将stomp.get_nowait()方法改用stomp.get()方法。

【ActiveMQ学习】Python语言整合ActiveMQ(时遇到的那些坑)_第6张图片

注意:作者在执行代码过程中遇到了一个奇怪的问题,按以上的代码执行时可能会报:Unexpected ACK received for message-id 的错误。错误的原因请参考:http://blog.csdn.net/kimmking/article/details/10162777

解决这个问题的方法涉及到stomp.subscribe()方法的参数:Client.subscribe(destination, ack='auto', conf=None),将参数ack的默认值"auto"改为ack="client"即可。

三、总结

ActiveMQ支持多种连接方式,网上常说的ActiveMQ默认端口:61616是openwire方式的默认端口。本文使用的是stomp协议连接,对应的是ActiveMQ的61613端口。打开ActiveMQ的配置文件activemq.xml可找到如下的端口对应代码:


        <!--
            The transport connectors expose ActiveMQ over a given protocol to
            clients and other brokers. For more information, see:

            http://activemq.apache.org/configuring-transports.html
        -->
        <transportConnectors>
            <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
            <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
        </transportConnectors>  



你可能感兴趣的:(【ActiveMQ学习】Python语言整合ActiveMQ(时遇到的那些坑))