rebbitMQ

1. 简单模式(Simple Mode)

  1. 生产者:

    • 连接到本地RabbitMQ服务器

    • 声明一个名为"hello"的队列

    • 向该队列发送一条消息

    • 使用默认交换机(空字符串)

  2. 消费者:

    • 连接到同一RabbitMQ服务器

    • 声明相同的队列

    • 设置回调函数处理接收到的消息

    • 自动确认消息(auto_ack=True)

  3. 特点:

    • 最简单的RabbitMQ使用模式

    • 一对一通信

    • 不需要显式创建交换机

    • 自动确认消息,适合简单场景

注意事项

  1. 如果先启动生产者,消息会存储在队列中直到消费者连接

  2. 这种简单模式没有消息持久化和手动确认机制

  3. 如需更可靠的消息处理,请参考工作队列模式

 

生产者

import pika

# 连接到RabbitMQ服务器
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

# 创建队列(如果不存在)
channel.queue_declare(queue='hello')

# 发送消息
message = "Hello RabbitMQ!"
channel.basic_publish(
    exchange='',  # 使用默认交换机
    routing_key='hello',  # 指定队列名称
    body=message
)
print(f" [x] Sent '{message}'")

# 关闭连接
connection.close()

消费者

import pika

# 定义消息处理回调函数
def callback(ch, method, properties, body):
    print(f" [x] Received {body.decode()}")

# 连接到RabbitMQ
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

# 声明队列(确保存在)
channel.queue_declare(queue='hello')

# 设置消费者
channel.basic_consume(
    queue='hello',  # 监听的队列名
    on_message_callback=callback,  # 消息处理函数
    auto_ack=True  # 自动确认消息
)

print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()  # 开始监听

 


2. 工作队列模式(Work Queue Mode)

工作队列模式(又称任务队列)用于在多个工作进程间分配耗时任务。

  1. 消息持久化:

    • 队列声明时设置 durable=True

    • 消息属性设置 delivery_mode=2

    • 确保RabbitMQ重启后队列和消息不丢失

  2. 公平分发:

    • basic_qos(prefetch_count=1) 确保每个worker一次只处理一个任务

    • 防止某些worker积压大量任务而其他worker空闲

  3. 消息确认:

    • auto_ack=False 关闭自动确认

    • 任务完成后手动调用 basic_ack

    • 确保任务不会在处理过程中丢失

应用场景

  • 异步处理耗时任务(如图片处理、视频转码)

  • 分布式任务分发

  • 负载均衡的场景

这个实现比简单模式更健壮,适合生产环境使用。如需更高级功能(如失败重试、优先级队列等),可以在基础上进一步扩展。

生产者

import pika
import sys

# 建立连接
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

# 声明持久化队列
channel.queue_declare(queue='task_queue', durable=True)

# 从命令行参数获取消息内容,默认发送5条测试消息
messages = sys.argv[1:] if len(sys.argv) > 1 else [
    f"Task {i}" for i in range(1, 6)
]

for message in messages:
    channel.basic_publish(
        exchange='',
        routing_key='task_queue',
        body=message.encode(),
        properties=pika.BasicProperties(
            delivery_mode=2,  # 使消息持久化
        )
    )
    print(f" [x] Sent '{message}'")

connection.close()

 

消费者

import pika
import time

# 消息处理回调函数
def callback(ch, method, properties, body):
    print(f" [x] Received {body.decode()}")
    # 模拟耗时任务,每个点号代表1秒
    time.sleep(body.count(b'.'))
    print(" [x] Done")
    # 手动发送确认消息
    ch.basic_ack(delivery_tag=method.delivery_tag)

# 建立连接
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

# 声明持久化队列
channel.queue_declare(queue='task_queue', durable=True)

# 设置公平分发,每次只给worker分配一个任务
channel.basic_qos(prefetch_count=1)

# 开始消费消息
channel.basic_consume(
    queue='task_queue',
    on_message_callback=callback,
    auto_ack=False  # 关闭自动确认
)

print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()

3. 发布/订阅模式(Publish/Subscribe)

发布/订阅模式使用 fanout 类型交换机,将消息广播给所有绑定的队列。

  1. fanout交换机:

    • 将消息广播到所有绑定的队列

    • 完全忽略routing_key

  2. 临时队列:

    • 使用 queue_declare(queue='', exclusive=True) 创建

    • 断开连接后自动删除

    • 适合临时订阅场景

  3. 队列绑定:

    • 必须将队列绑定到交换机才能接收消息

    • 绑定可以动态添加/移除

应用场景

  • 系统日志广播

  • 事件通知(如订单创建通知多个子系统)

  • 实时数据分发(如股票价格更新)

扩展功能

  1. 持久化订阅:

    • 使用固定队列名(非临时队列)

    • 消费者离线时消息不会丢失

  2. 选择性订阅:

    • 改用 topic 交换机实现部分消息过滤

  3. 消息持久化:

    • 添加 delivery_mode=2 属性

    • 交换机/队列声明时设置 durable=True

这个模式适合需要"一对多"广播的场景,所有订阅者都会收到相同的消息副本。

生产者

import pika
import sys

# 建立连接
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

# 声明fanout类型交换机(日志交换机)
channel.exchange_declare(exchange='logs', exchange_type='fanout')

# 从命令行获取消息内容,默认发送测试消息
message = ' '.join(sys.argv[1:]) or "info: Hello World!"

# 发布消息到交换机(不需要指定routing_key)
channel.basic_publish(
    exchange='logs',
    routing_key='',  # fanout类型忽略routing_key
    body=message.encode()
)
print(f" [x] Sent '{message}'")

connection.close()

 

消费者

import pika

# 建立连接
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

# 声明fanout类型交换机(必须与生产者一致)
channel.exchange_declare(exchange='logs', exchange_type='fanout')

# 声明临时队列(exclusive=True表示断开连接后自动删除)
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue

# 将队列绑定到交换机
channel.queue_bind(exchange='logs', queue=queue_name)

print(' [*] Waiting for logs. To exit press CTRL+C')

def callback(ch, method, properties, body):
    print(f" [x] {body.decode()}")

# 开始消费
channel.basic_consume(
    queue=queue_name,
    on_message_callback=callback,
    auto_ack=True
)

channel.start_consuming()

 

 

 


4. 路由模式(Routing Mode)

路由模式使用 direct 类型交换机,通过 routing_key 精确匹配队列绑定键。

这个模式非常适合需要按消息类型分类处理的场景,如日志系统、订单状态流转等。

生产者

import pika
import sys

# 建立连接
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

# 声明direct类型交换机(持久化)
channel.exchange_declare(exchange='direct_logs',
                        exchange_type='direct',
                        durable=True)

# 从命令行获取参数
severity = sys.argv[1] if len(sys.argv) > 1 else 'info'
message = ' '.join(sys.argv[2:]) or 'Hello Direct Routing!'

# 发布消息(指定routing_key)
channel.basic_publish(
    exchange='direct_logs',
    routing_key=severity,  # 关键路由键
    body=message,
    properties=pika.BasicProperties(
        delivery_mode=2,  # 消息持久化
    )
)
print(f" [x] Sent to '{severity}': '{message}'")

connection.close()

 

消费者

import pika
import sys

# 建立连接
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

# 声明相同的direct交换机
channel.exchange_declare(exchange='direct_logs',
                        exchange_type='direct',
                        durable=True)

# 创建临时队列
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue

# 绑定路由键(从命令行获取)
severities = sys.argv[1:]
if not severities:
    sys.stderr.write(f"Usage: {sys.argv[0]} [info] [warning] [error]\n")
    sys.exit(1)

for severity in severities:
    channel.queue_bind(exchange='direct_logs',
                      queue=queue_name,
                      routing_key=severity)

print(' [*] Waiting for logs. To exit press CTRL+C')

def callback(ch, method, properties, body):
    print(f" [x] {method.routing_key}:{body.decode()}")

channel.basic_consume(queue=queue_name,
                     on_message_callback=callback,
                     auto_ack=True)

channel.start_consuming()

 

 

 


5. 主题模式(Topics Mode)

主题模式使用 topic 类型交换机,通过带通配符的 routing_key 实现灵活的消息路由。

主题模式非常适合需要多维度消息分类的场景,如:

  • 多地区订单处理(region.orders.type

  • 设备状态监控(device.type.status

  • 多层级的日志分类系统

 

 

 

 

 

 


6. RPC 模式(Remote Procedure Call)

 

 

 

 


其他高级模式

  1. Headers 模式

    • 交换机类型:headers

    • 路由规则:通过消息头(headers)键值对匹配,而非 routing_key

    • 适用场景:复杂条件路由(如同时满足多个条件)。

  2. 死信队列(DLX)

    • 处理被拒绝或过期的消息。

    • 关键配置:x-dead-letter-exchange 指定死信交换机。

  3. 延迟队列

    • 实现方式:消息 TTL + 死信队列。

    • 适用场景:定时任务(如订单超时取消)。

    •  
posted @ 2025-06-15 20:51  liuun  阅读(21)  评论(0)    收藏  举报