[Python学习笔记-006] 使用stomp.py校验JMS selector的正确性
了解Jenkins的人都知道,JMS selector是基于SQL92语法实现的,本文将介绍使用stomp.py和ActiveMQ来校验JMS selector的正确性。
Q: 什么是stomp.py?
A: stomp.py是一个基于STOMP(Simple (or Streaming) Text Orientated Messaging Protocol)协议实现的Python的客户端函数库,用来访问诸如ActiveMQ,RabbitMQ之类的消息服务器。
那么,为了使用stomp.py函数库,我们先安装一个ActiveMQ服务。
1. 下载ActiveMQ
$ export TGZBALL=5.15./apache-activemq-5.15.-bin.tar.gz
$ wget https://archive.apache.org/dist/activemq/$TGZBALL
2. 安装ActiveMQ
$ tar zxvf apache-activemq-5.15.-bin.tar.gz
$ sudo mv apache-activemq-5.15. /opt
$ cd /opt
$ sudo ln -s apache-activemq-5.15. activemq
3. 启动ActiveMQ
$ cd /opt/activemq/bin/linux-x86-
$ sudo ./activemq start
Starting ActiveMQ Broker...
注意ActiveMQ默认的监听端口是8161,
$ netstat -an | egrep
tcp6 ::: :::* LISTEN
如果要关闭ActiveMQ,
$ cd /opt/activemq/bin/linux-x86-
$ sudo ./activemq stop
Stopping ActiveMQ Broker...
Stopped ActiveMQ Broker.
一旦ActiveMQ, 我们可以访问其web界面,默认的登录用户名/密码是admin/admin, 例如:

4. 克隆stomp.py的源代码
$ mkdir /var/tmp/sp
$ cd /var/tmp/sp
$ git clone https://github.com/jasonrbriggs/stomp.py.git
5. 准备一个Python脚本foo.py
#!/usr/bin/python3
import sys
import json
import collections
import time
import stomp g_rcvmsg_cnt = 0 # counter of received messages class MyListener(stomp.ConnectionListener):
def on_error(self, headers, message):
global g_rcvmsg_cnt
g_rcvmsg_cnt = 0 print('Oops!! received an error "%s"' % message) def on_message(self, headers, message):
global g_rcvmsg_cnt
g_rcvmsg_cnt += 1 print('Bingo! received a message, rcv_cnt = %d' % g_rcvmsg_cnt)
print('o message headers :\n%s' % json.dumps(headers, indent=4))
print('o message body : %s\n' % message) def validate():
if g_rcvmsg_cnt > 0:
print(">>> PASS")
return 0
else:
print(">>> FAIL")
return 1 def usage(argv0):
sys.stderr.write("Usage: %s <JMS selector> <message headers>\n" % argv0) def main(argc, argv):
if argc != 3:
usage(argv[0])
return 1 jms_selector = argv[1]
msg_headers = argv[2] d_sub_headers = dict()
d_sub_headers['selector'] = jms_selector
print('>>> SUB HEADERS', d_sub_headers) d_snd_headers = json.loads(msg_headers,
object_pairs_hook=collections.OrderedDict)
print('>>> SND HEADERS', d_snd_headers)
print() conn = stomp.Connection()
conn.set_listener('', MyListener())
conn.start() # Note default user/password of ActiveMQ is admin/admin
user = 'admin'
password = 'admin'
conn.connect(user, password, wait=True) conn.subscribe(destination='/queue/test', id=1, ack='auto',
headers=d_sub_headers) s_body = ' '.join(argv[1:])
conn.send(destination='/queue/test', body=s_body, headers=d_snd_headers) time.sleep(2)
conn.disconnect() return validate() if __name__ == '__main__':
sys.exit(main(len(sys.argv), sys.argv))
在上面的代码中,
67 conn.subscribe(destination='/queue/test', id=1, ack='auto',
68 headers=d_sub_headers)
L67-68: 根据用户输入的JMS selector进行订阅,
71 conn.send(destination='/queue/test', body=s_body, headers=d_snd_headers)
L71: 将用户输入的JSON文本作为消息头发送。
6. 使用foo.py测试JMS selector
hdan$ export PYTHONPATH=/var/tmp/sp/stomp.py:$PYTHONPATH
hdan$
hdan$ ./foo.py "Type LIKE 'Tag%'" '{"Type": "tag", "foo": 123}'
>>> SUB HEADERS {'selector': "Type LIKE 'Tag%'"}
>>> SND HEADERS OrderedDict([('Type', 'tag'), ('foo', )]) >>> FAIL
hdan$
hdan$ ./foo.py "Type LIKE 'Tag%'" '{"Type": "Tag", "foo": 123}'
>>> SUB HEADERS {'selector': "Type LIKE 'Tag%'"}
>>> SND HEADERS OrderedDict([('Type', 'Tag'), ('foo', )]) Bingo! received a message, rcv_cnt =
o message headers :
{
"subscription": "",
"content-length": "",
"timestamp": "",
"destination": "/queue/test",
"message-id": "ID:huangdan-40431-1550639739706-3:131:-1:1:1",
"foo": "",
"Type": "Tag",
"expires": "",
"priority": ""
}
o message body : Type LIKE 'Tag%' {"Type": "Tag", "foo": } >>> PASS
hdan$
hdan$ ./foo.py "Type LIKE 'Tag%'" '{"Type": "Tag123", "foo": 123}'
>>> SUB HEADERS {'selector': "Type LIKE 'Tag%'"}
>>> SND HEADERS OrderedDict([('Type', 'Tag123'), ('foo', )]) Bingo! received a message, rcv_cnt =
o message headers :
{
"message-id": "ID:huangdan-40431-1550639739706-3:132:-1:1:1",
"destination": "/queue/test",
"timestamp": "",
"expires": "",
"priority": "",
"subscription": "",
"content-length": "",
"foo": "",
"Type": "Tag123"
}
o message body : Type LIKE 'Tag%' {"Type": "Tag123", "foo": } >>> PASS
hdan$
附录: SQL92的LIKE操作符 (来源戳这里)
A like string consists of a set of characters where the percent (%),
underscore (_) and escape character, such as backslash (\) are
treated differently. * The percent (%) matches any number of characters including
zero characters
* The underscore (_) matches only one character e.g.
+-------------+---------------------------------------+
| Like string | Meaning |
+-------------+---------------------------------------+
| Topic% | All strings starting with Topic |
| %/abc/% | Any string containing /abc/ |
| Name_ | Any string starting with Name and |
| | having exactly one more character |
| Name\_2 | Only the string Name_2 |
+-------------+---------------------------------------+
参考资料:
[Python学习笔记-006] 使用stomp.py校验JMS selector的正确性的更多相关文章
- Python学习笔记006
算术运算符 加+ 减- 乘* 除/ 整除//,地板除 取余% 指数** ()区分 优先级 比较运算符 赋值 = 等于 == 不等于 != 大于等于 >= 小于等于 <=
- Python学习笔记:装饰器
Python 装饰器的基本概念和应用 代码编写要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即: 封闭:已 ...
- VS2013中Python学习笔记[Django Web的第一个网页]
前言 前面我简单介绍了Python的Hello World.看到有人问我搞搞Python的Web,一时兴起,就来试试看. 第一篇 VS2013中Python学习笔记[环境搭建] 简单介绍Python环 ...
- python学习笔记之module && package
个人总结: import module,module就是文件名,导入那个python文件 import package,package就是一个文件夹,导入的文件夹下有一个__init__.py的文件, ...
- python学习笔记(六)文件夹遍历,异常处理
python学习笔记(六) 文件夹遍历 1.递归遍历 import os allfile = [] def dirList(path): filelist = os.listdir(path) for ...
- python学习笔记--Django入门四 管理站点--二
接上一节 python学习笔记--Django入门四 管理站点 设置字段可选 编辑Book模块在email字段上加上blank=True,指定email字段为可选,代码如下: class Autho ...
- python学习笔记--Django入门0 安装dangjo
经过这几天的折腾,经历了Django的各种报错,翻译的内容虽然不错,但是与实际的版本有差别,会出现各种奇葩的错误.现在终于找到了解决方法:查看英文原版内容:http://djangobook.com/ ...
- Python学习笔记(十三)
Python学习笔记(十三): 模块 包 if name == main 软件目录结构规范 作业-ATM+购物商城程序 1. 模块 1. 模块导入方法 import 语句 import module1 ...
- Python学习笔记(十一)
Python学习笔记(十一): 生成器,迭代器回顾 模块 作业-计算器 1. 生成器,迭代器回顾 1. 列表生成式:[x for x in range(10)] 2. 生成器 (generator o ...
随机推荐
- android 获取 imei号码
Imei = ((TelephonyManager) getSystemService(TELEPHONY_SERVICE)) .getDeviceId(); 1.加入权限 在manifest.xml ...
- JS产生徐特尔图表
徐特尔图表是一个小游戏,在5*5的格子上,无序的写着1~25这25个数子,然后再找出来.其实在JS中也就是将25个数进行随机产生然后放到一个表格中.主要分为两部分,一是随机数的产生,还有一部分就是表格 ...
- 【CF995F】 Cowmpany Cowmpensation
CF995F Cowmpany Cowmpensation Solution 这道题目可以看出我的代码能力是有多渣(代码能力严重退化) 我们先考虑dp,很容易写出方程: 设\(f_{i,j}\)表示以 ...
- Android 使用 NYTimes Stores 缓存 network request
NYTimes Stores 是一个缓存库,在 2017年的 AndroidMakers 大会上被介绍过. https://github.com/NYTimes/Store 实现一个 Disk Cac ...
- springboot2 生产部署注意事项【持续更新】
注意事项1. 去除不需要的 jar 开发工具 jar :springs-boot-devtools2. 监控一定要做好权限制或者去除 控制 jar :spring-boot-starter-actua ...
- kali linux 安装sublime text3完全教程
点击进入官网 下载页面 将鼠标放在64 bit(64位系统)上右击复制链接 打开终端: #wget 路径(粘贴刚复制的) #tar -xvvf 刚刚下载的文件文件名(解压) #mv 解压出来的文件名 ...
- [转载]Java并发编程:深入剖析ThreadLocal
原文地址:http://www.cnblogs.com/dolphin0520/p/3920407.html 想必很多朋友对ThreadLocal并不陌生,今天我们就来一起探讨 ...
- gulp 打包错误 TypeError: Path must be string. Received undefined
Running gulp gives “path.js:7 throw new TypeError('Path must be a string. Received ' + inspect(path) ...
- log4j的日志级别(ssm中log4j的配置)
log4j定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从高到低依次为:OFF.FATAL.ERROR.WARN.INFO.DEBUG.TRACE. ALL. 1. ALL ...
- 利用django-simple-captcha生成验证码
参考文档 http://django-simple-captcha.readthedocs.io/en/latest/ django支持1.7+ 1.安装 pip install django-sim ...