python实现RabbitMQ的消息队列的示例代码


Posted in Python onNovember 08, 2018

最近在研究redis做消息队列时,顺便看了一下RabbitMQ做消息队列的实现。以下是总结的RabbitMQ中三种exchange模式的实现,分别是fanout, direct和topic。

base.py:

import pika
# 获取认证对象,参数是用户名、密码。远程连接时需要认证
credentials = pika.PlainCredentials("admin", "admin")

# BlockingConnection(): 实例化连接对象
# ConnectionParameters(): 实例化链接参数对象
connection = pika.BlockingConnection(pika.ConnectionParameters(
  "192.168.0.102", 5672, "/", credentials))

# 创建新的channel(通道)
channel = connection.channel()

fanout模式:向绑定到指定exchange的queue中发送消息,消费者从queue中取出数据,类似于广播模式、发布订阅模式。
绑定方式: 在接收端channel.queue_bind(exchange="logs", queue=queue_name)

代码:

publisher.py:

from base import channel, connection
# 声明exchange, 不声明queue
channel.exchange_declare(exchange="logs", exchange_type="fanout") # 广播
message = "hello fanout"
channel.basic_publish(
  exchange="logs",
  routing_key="",
  body=message
)
connection.close()

consumer.py:

from base import channel, connection
    
# 声明exchange
channel.exchange_declare(exchange="logs", exchange_type="fanout")

# 不指定queue名字, rabbitmq会随机分配一个名字, 消息处理完成后queue会自动删除
result = channel.queue_declare(exclusive=True) 

# 获取queue名字
queue_name = result.method.queue

# 绑定exchange和queue
channel.queue_bind(exchange="logs", queue=queue_name)


def callback(ch, method, properties, body):
  print("body:%s" % body)


channel.basic_consume(
  callback,
  queue=queue_name
)


channel.start_consuming()

direct模式:发送端绑定一个routing_key1, queue中绑定若干个routing_key2, 若key1与key2相等,或者key1在key2中,则消息就会发送到这个queue中,再由相应的消费者去queue中取数据。

publisher.py:

from base import channel, connection
channel.exchange_declare(exchange="direct_test", exchange_type="direct")

message = "hello"

channel.basic_publish(
  exchange="direct_test",
  routing_key="info", # 绑定key
  body=message
)
connection.close()

consumer01.py:

from base import channel, connection
      
      
channel.exchange_declare(exchange="direct_test", exchange_type="direct")
result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue


channel.queue_bind(
  exchange="direct_test",
  queue=queue_name,
  # 绑定的key,与publisher中的相同
  routing_key="info" 
)


def callback(ch, method, properties, body):
  print("body:%s" % body)


channel.basic_consume(
  callback,
  queue=queue_name
)


channel.start_consuming()

consumer02.py:

from base import channel, connection


channel.exchange_declare(exchange="direct_test", exchange_type="direct")
result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue


channel.queue_bind(
  exchange="direct_test",
  queue=queue_name,
  # 绑定的key
  routing_key="error"  
)


def callback(ch, method, properties, bosy):
  print("body:%s" % body)


channel.basic_consume(
  callback,
  queue=queue_name
)


channel.start_consuming()

consumer03.py:

from base import channel, connection
      
      
channel.exchange_declare(exchange="direct_test", exchange_type="direct")
result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue


key_list = ["info", "warning"]
for key in key_list:
  channel.queue_bind(
    exchange="direct_test",
    queue=queue_name,
    # 一个queue同时绑定多个key,有一个key满足条件时就可以收到数据
    routing_key=key 
  )


def callback(ch, method, properties, body):
  print("body:%s" % body)


channel.basic_consume(
  callback,
  queue=queue_name
)


channel.start_consuming()

执行:

python producer.py
python consumer01.py
python consumer02.py
python consumer03.py

结果:

consumer01.py: body:b'hello'
consumer02.py没收到结果
consumer03.py: body:b'hello'

topic模式不是太好理解,我的理解如下:

对于发送端绑定的routing_key1,queue绑定若干个routing_key2;若routing_key1满足任意一个routing_key2,则该消息就会通过exchange发送到这个queue中,然后由接收端从queue中取出其实就是direct模式的扩展。

绑定方式:

发送端绑定:

channel.basic_publish(
    exchange="topic_logs",
    routing_key=routing_key,
    body=message
  )

接收端绑定:

channel.queue_bind(
    exchange="topic_logs",
    queue=queue_name,
    routing_key=binding_key
  )

publisher.py:

import sys
from base import channel, connection


# 声明exchange
channel.exchange_declare(exchange="topic_test", exchange_type="topic")

# 待发送消息
message = " ".join(sys.argv[1:]) or "hello topic"

# 发布消息
channel.basic_publish(
  exchange="topic_test",
  routing_key="mysql.error",  # 绑定的routing_key
  body=message
)
connection.close()

consumer01.py:

from base import channel, connection
      
      
channel.exchange_declare(exchange="topic_test", exchange_type="topic")
result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue


channel.queue_bind(
  exchange="topic_test",
  queue=queue_name,
  routing_key="*.error"  # 绑定的routing_key
)


def callback(ch, method, properties, body):
  print("body:%s" % body)


channel.basic_consume(
  callback,
  queue=queue_name,
  no_ack=True
)


channel.start_consuming()

consumer02.py:

from base import channel, connection
      
      
channel.exchange_declare(exchange="topic_test", exchange_type="topic")
result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue


channel.queue_bind(
  exchange="topic_test",
  queue=queue_name,
  routing_key="mysql.*"  # 绑定的routing_key
)


def callback(ch, method, properties, body):
  print("body:%s" % body)


channel.basic_consume(
  callback,
  queue=queue_name,
  no_ack=True
)


channel.start_consuming()

执行:

python publisher02.py "this is a topic test"
python consumer01.py
python consumer02.py

结果:

consumer01.py的结果: body:b'this is a topic test'
consumer02.py的结果: body:b'this is a topic test'

说明通过绑定相应的routing_key,两个消费者都收到了消息

将publisher.py的routing_key改成"mysql.info"

再此执行:

python publisher02.py "this is a topic test"
python consumer01.py
python consumer02.py

结果:

consumer01.py没收到结果
consumer02.py的结果: body:b'this is a topic test'

通过这个例子我们就能明白topic的运行方式了。

参考自: https://3water.com/article/150386.htm

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
跟老齐学Python之使用Python查询更新数据库
Nov 25 Python
用Python中的__slots__缓存资源以节省内存开销的方法
Apr 02 Python
深入讲解Java编程中类的生命周期
Feb 05 Python
解决python3爬虫无法显示中文的问题
Apr 12 Python
如何通过雪花算法用Python实现一个简单的发号器
Jul 03 Python
在python中将list分段并保存为array类型的方法
Jul 15 Python
python爬虫爬取监控教务系统的思路详解
Jan 08 Python
使用Python来做一个屏幕录制工具的操作代码
Jan 18 Python
python将logging模块封装成单独模块并实现动态切换Level方式
May 12 Python
Django 构建模板form表单的两种方法
Jun 14 Python
详解python 内存优化
Aug 17 Python
互斥锁解决 Python 中多线程共享全局变量的问题(推荐)
Sep 28 Python
对Python 3.5拼接列表的新语法详解
Nov 08 #Python
Python使用random.shuffle()打乱列表顺序的方法
Nov 08 #Python
python RabbitMQ 使用详细介绍(小结)
Nov 08 #Python
如何利用Boost.Python实现Python C/C++混合编程详解
Nov 08 #Python
python训练数据时打乱训练数据与标签的两种方法小结
Nov 08 #Python
对Python random模块打乱数组顺序的实例讲解
Nov 08 #Python
Python中对数组集进行按行打乱shuffle的方法
Nov 08 #Python
You might like
PHP 第二节 数据类型之数值型
2012/04/28 PHP
PHP 搜索查询功能实现
2016/11/29 PHP
Yii2实现ActiveForm ajax提交
2017/05/26 PHP
PHP实现动态获取函数参数的方法示例
2018/04/02 PHP
Laravel框架定时任务2种实现方式示例
2018/12/08 PHP
win10下 php安装seaslog扩展的详细步骤
2020/12/04 PHP
新闻内页-JS分页
2006/06/07 Javascript
js常用函数 不错
2006/09/08 Javascript
Javascript里使用Dom操作Xml
2007/01/22 Javascript
css把超出的部分显示为省略号的方法兼容火狐
2008/07/23 Javascript
Javascript中的相等与不等运算
2010/04/25 Javascript
JavaScript中对象property的删除方法介绍
2014/12/30 Javascript
jQuery获取attr()与prop()属性值的方法及区别介绍
2016/07/06 Javascript
Angular2 PrimeNG分页模块学习
2017/01/14 Javascript
JavaScript运动框架 解决速度正负取整问题(一)
2017/05/17 Javascript
vue服务端渲染添加缓存的方法
2018/09/18 Javascript
深入理解react-router 路由的实现原理
2018/09/26 Javascript
vue-router为激活的路由设置样式操作
2020/07/18 Javascript
Vue实现返回顶部按钮实例代码
2020/10/21 Javascript
[12:51]71泪洒现场!是DOTA2让经典重现
2014/03/24 DOTA
Python排序搜索基本算法之归并排序实例分析
2017/12/08 Python
Python OpenCV 直方图的计算与显示的方法示例
2018/02/08 Python
pycharm 将django中多个app放到同个文件夹apps的处理方法
2018/05/30 Python
对python程序内存泄漏调试的记录
2018/06/11 Python
Python实现的远程文件自动打包并下载功能示例
2019/07/12 Python
pyinstaller打包程序exe踩过的坑
2019/11/19 Python
python 6种方法实现单例模式
2020/12/15 Python
Ooni英国官网:披萨烤箱
2020/05/31 全球购物
超市实习总结自我鉴定
2013/09/19 职场文书
护理自荐信范文
2013/10/05 职场文书
安全生产先进个人材料
2014/02/06 职场文书
企业党员公开承诺书
2014/03/26 职场文书
公司档案管理制度
2015/08/05 职场文书
2016中学教师读书心得体会
2016/01/13 职场文书
《吃水不忘挖井人》教学反思
2016/02/22 职场文书
Python中re模块的元字符使用小结
2022/04/07 Python