RabbitMQ上手
MQ
即消息队列, 一种应用程序间的通信方法,生产者-消费者模型的典型实践。
生产者-消费者模式通过一个容器来解决生产者和消费者的强耦合问题,生产者和消费者通过一个阻塞队列进行通讯。
作用和意义
消息队列中间件是分布式系统中重要的组件,主要解决应用解耦、异步消息、流量消峰等问题。
安装部署
https://help.aliyun.com/document_detail/53100.html#section-gr4-zy1-ffb
应用模式
简单模式
生产者行为:
连接rabbitmq
创建队列
向队列中插入数据
import pika
# 连接rabbitmq
connection = pika.BlockingConnection(pika.ConnectionParameters(host='server_host',
credentials=pika.credentials.PlainCredentials('user',
'password')))
channel = connection.channel()
# 声明队列(如不存在则创建,已存在则忽略)
channel.queue_declare(queue='hello')
# 向指定队列插入数据
channel.basic_publish(exchange='', routing_key='hello', body=b'Hello World!')
消费者行为:
连接rabbitmq
监听指定队列
确定回调函数
import pika
# 连接rabbitmq
connection = pika.BlockingConnection(pika.ConnectionParameters(host='server_host',
credentials=pika.credentials.PlainCredentials('user',
'password')))
channel = connection.channel()
# 声明队列(如不存在则创建,已存在则忽略)
channel.queue_declare(queue='hello')
# 定义回调函数
def callback(ch, method, properties, body):
print(f'本次取得的数据为{body.decode()}') # body为bytes类型
# 确定监听队列和参数
channel.basic_consume(queue='hello', auto_ack=True, on_message_callback=callback)
print('即将开始监听队列hello')
# 开始监听
channel.start_consuming()
参数
应答参数
为避免回调函数内部错误造成队列中的消息丢失,在确保回调函数内部逻辑执行完毕后手动应答来通知队列删除被处理完毕的消息。
应:1.修改监听参数中auto_ack的值为False;2.在回调函数内部、处理语句结束后添加手动应答语句
import pika
# 连接rabbitmq
connection = pika.BlockingConnection(pika.ConnectionParameters(host='server_host',
credentials=pika.credentials.PlainCredentials('user',
'password')))
channel = connection.channel()
# 声明队列(如不存在则创建,已存在则忽略)
channel.queue_declare(queue='hello')
# 定义回调函数
def callback(ch, method, properties, body):
print(f'本次取得的数据为{body.decode()}') # body为bytes类型
# 二、执行完内部处理逻辑后添加手动应答语句
ch.basic_ack(delivery_tag=method.delivery_tag)
# 确定监听队列和参数 一、修改auto_ack为false, 即手动应答
channel.basic_consume(queue='hello', auto_ack=False, on_message_callback=callback)
print('即将开始监听队列hello')
# 开始监听
channel.start_consuming()
持续化参数
避免因服务器崩溃导致重要的消息在未处理前丢失。
1.在生产者和消费者都声明可持久化队列(无法将已声明为不可持久化的队列转为可持久化队列)
channel.queue_declare(queue='hello2', durable=True)
2.生产者指定某条数据持久化
# 向指定队列插入数据 指定本次数据为持久化
channel.basic_publish(exchange='', routing_key='hello2', body=b'Hello World!', properties=pika.BasicProperties(
delivery_mode=2,
))
3.确保手动应答
# 定义回调函数
def callback(ch, method, properties, body):
print(f'本次取得的数据为{body.decode()}') # body为bytes类型
# 执行完内部处理逻辑后添加手动应答语句
ch.basic_ack(delivery_tag=method.delivery_tag)
# 确定监听队列和参数 修改auto_ack为false, 即手动应答
channel.basic_consume(queue='hello2', auto_ack=False, on_message_callback=callback)
分发参数
避免由默认的轮询模式导致服务器压力不公平
import pika
# 连接rabbitmq
connection = pika.BlockingConnection(pika.ConnectionParameters(host='server_host',
credentials=pika.credentials.PlainCredentials('user',
'password')))
channel = connection.channel()
# 声明队列(如不存在则创建,已存在则忽略)
channel.queue_declare(queue='hello3')
# 定义回调函数
def callback(ch, method, properties, body):
print(f'本次取得的数据为{body.decode()}') # body为bytes类型
# 执行完内部处理逻辑后添加手动应答语句
ch.basic_ack(delivery_tag=method.delivery_tag)
# ☆设置分发参数
channel.basic_qos(prefetch_count=1)
# 确定监听队列和参数 修改auto_ack为false, 即手动应答
channel.basic_consume(queue='hello3', auto_ack=False, on_message_callback=callback)
print('即将开始监听队列hello')
# 开始监听
channel.start_consuming()
交换机模式
发布订阅模式
生产者行为:
声明交换机(模式为发布订阅)、向交换机中插入数据
import pika
# 连接rabbitmq
connection = pika.BlockingConnection(pika.ConnectionParameters(host='server_host',
credentials=pika.credentials.PlainCredentials('user',
'password')))
channel = connection.channel()
# 声明名为logs的交换机,声明交换机模式为发布订阅
channel.exchange_declare(exchange='logs', exchange_type='fanout')
channel.basic_publish(exchange='logs', routing_key='', body=b'Hello World!2')
connection.close()
消费者行为:
声明交换机(模式为发布订阅)、创建队列、将队列绑定到交换机、监听队列
import pika
# 连接rabbitmq
connection = pika.BlockingConnection(pika.ConnectionParameters(host='server_host',
credentials=pika.credentials.PlainCredentials('user',
'password')))
channel = connection.channel()
# 声明名为logs的交换机,声明交换机模式为发布订阅
channel.exchange_declare(exchange='logs', exchange_type='fanout')
# 创建队列
q = channel.queue_declare('', exclusive=True)
q_name = q.method.queue
# 将队列绑定到交换机
channel.queue_bind(exchange='logs', queue=q_name)
def callback(ch, method, properties, body):
print(f'本次取得的数据为:{body.decode()}')
channel.basic_consume(queue=q_name, auto_ack=True, on_message_callback=callback)
channel.start_consuming()
关键字模式
生产者行为:
声明交换机exchange_type为direct、发布数据时提供routing_key
import pika
# 连接rabbitmq
connection = pika.BlockingConnection(pika.ConnectionParameters(host='server_host',
credentials=pika.credentials.PlainCredentials('user',
'password')))
channel = connection.channel()
# 声明名为logs的交换机,声明交换机模式为发布订阅
channel.exchange_declare(exchange='logs2', exchange_type='direct')
channel.basic_publish(exchange='logs2', routing_key='success', body=b'success')
connection.close()
消费者行为:
声明交换机exchange_type为direct、绑定交换机时提供routing_key(绑定多个关键字需多条语句声明)
import pika
# 连接rabbitmq
connection = pika.BlockingConnection(pika.ConnectionParameters(host='server_host',
credentials=pika.credentials.PlainCredentials('user',
'password')))
channel = connection.channel()
# 声明名为logs2的交换机,声明交换机模式为发布订阅
channel.exchange_declare(exchange='logs2', exchange_type='direct')
# 创建队列
q = channel.queue_declare('', exclusive=True)
q_name = q.method.queue
# 将队列绑定到交换机
channel.queue_bind(exchange='logs2', queue=q_name, routing_key='err')
def callback(ch, method, properties, body):
print(f'本次取得的数据为:{body.decode()}')
channel.basic_consume(queue=q_name, auto_ack=True, on_message_callback=callback)
channel.start_consuming()
通配符模式
生产者行为:
声明交换机时exchange_type设置为topic、发布数据时提供routing_key
import pika
# 连接rabbitmq
connection = pika.BlockingConnection(pika.ConnectionParameters(host='server_host',
credentials=pika.credentials.PlainCredentials('user',
'password')))
channel = connection.channel()
# 声明名为logs的交换机,声明交换机模式为发布订阅
channel.exchange_declare(exchange='logs6', exchange_type='topic')
channel.basic_publish(exchange='logs6', routing_key='class.object', body=b'object.class')
connection.close()
消费者行为:
声明交换机时exchange_type设置为topic、绑定交换机时提供routing_key
import pika
# 连接rabbitmq
connection = pika.BlockingConnection(pika.ConnectionParameters(host='server_host',
credentials=pika.credentials.PlainCredentials('user',
'password')))
channel = connection.channel()
# 声明名为logs2的交换机,声明交换机模式为发布订阅
channel.exchange_declare(exchange='logs6', exchange_type='topic')
# 创建队列
q = channel.queue_declare('', exclusive=True)
q_name = q.method.queue
# 将队列绑定到交换机
channel.queue_bind(exchange='logs6', queue=q_name, routing_key='object.#')
def callback(ch, method, properties, body):
print(f'本次取得的数据为:{body.decode()}')
channel.basic_consume(queue=q_name, auto_ack=True, on_message_callback=callback)
print('消费者object.#')
channel.start_consuming()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现