《10 分钟上手 RabbitMQ:用 Python 写一个“不丢消息”的迷你消息系统》

标签:

RabbitMQ · Python · 消息队列 · 实战 Demo · 入门


为什么写这篇?

消息队列(MQ)的概念大家背得滚瓜烂熟:解耦、异步、削峰。但"第一次把消息真正发出去"的门槛依旧不小:

  • 需要装 Erlang?
  • 管理界面怎么开?
  • 消息会不会一发就丢?

这篇文章带你 10 分钟跑通第一个可生产的 RabbitMQ 示例,代码不足 80 行,却覆盖持久化 + 手动 ACK + 连接断线重试等生产级要素,复制即可运行。


1. 一键启动 RabbitMQ

不想装 Erlang?Docker 一把梭:

bash 复制代码
docker run -d --hostname rabbit \
  --name rabbit \
  -p 5672:5672 \
  -p 15672:15672 \
  rabbitmq:3.12-management

浏览器打开 http://localhost:15672

账号/密码:guest / guest

能看到队列、消息速率、节点内存,调试神器 get✔


2. Python 依赖仅一个包

bash 复制代码
pip install pika==1.3.2

3. 队列与消息:先声明,再使用

RabbitMQ 的哲学:队列只创建一次,谁先到谁声明

示例里把 durable=True 打开,即使 MQ 重启,队列元数据也不会丢。


4. 生产者代码(producer.py

python 复制代码
import pika, sys

QUEUE = 'demo_queue'

def main():
    conn = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
    ch = conn.channel()
    ch.queue_declare(queue=QUEUE, durable=True)          # 持久化队列

    for i in range(10):
        body = f'hello {i}'
        ch.basic_publish(exchange='',
                         routing_key=QUEUE,
                         body=body,
                         properties=pika.BasicProperties(delivery_mode=2))  # 持久化消息
        print(f' [x] Sent "{body}"')
    conn.close()

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        sys.exit()

运行结果:

csharp 复制代码
 [x] Sent "hello 0"
 [x] Sent "hello 1"
 ...
 [x] Sent "hello 9"

5. 消费者代码(consumer.py

python 复制代码
import pika, time, sys

QUEUE = 'demo_queue'

def callback(ch, method, properties, body):
    print(f' [x] Received {body.decode()}')
    time.sleep(1)                               # 模拟耗时
    print(' [x] Done')
    ch.basic_ack(delivery_tag=method.delivery_tag)  # 手动 ack

def main():
    conn = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
    ch = conn.channel()
    ch.queue_declare(queue=QUEUE, durable=True)
    ch.basic_qos(prefetch_count=1)              # 公平分发
    ch.basic_consume(queue=QUEUE, on_message_callback=callback)
    print(' [*] Waiting for messages. To exit press CTRL+C')
    ch.start_consuming()

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        sys.exit()

运行后,每秒处理 1 条消息,10 秒完成全部任务;

RabbitMQ UI 中 Messages 从 10 → 0,没有一条积压。


6. 小结:我们到底做了什么?

关键点 命令/参数 作用
队列持久化 queue_declare(durable=True) MQ 重启队列不丢
消息持久化 delivery_mode=2 服务器掉电消息不丢
手动 ACK basic_ack 消费者崩溃时消息可重新投递
公平分发 basic_qos(prefetch_count=1) 慢消费者不会被压垮

把这 4 项配置搬到生产环境,你就已经战胜了 80% 的"消息丢失"事故。


7. 下一步可以玩什么?

  1. demo_queue 换成 topic 模式,实现日志级别路由;
  2. RPC 模式做同步调用,假装自己是一个微服务网关;
  3. 开镜像队列 + 集群,Kill 掉任一节点,消息依旧在线;
  4. 给消费端加 retry + dead-letter-exchange,自动重试 3 次后进入死信队列,人工处理。

8. 一句鸡汤

消息队列的难点从来不在于"发消息",而在于"失败时消息还在"。

先让今天的 10 条消息不丢,再去考虑百万 QPS 的宏伟蓝图------脚下已出发,远方不远。

完整源码已上传 GitHub:
github.com/yourname/ra...

欢迎 Star & PR,祝大家排队愉快!

相关推荐
YDS8291 天前
SpringCloud —— RabbitMQ消息队列详解
spring cloud·rabbitmq·java-rabbitmq
java1234_小锋1 天前
RabbitMQ和AMQP是什么关系?
分布式·rabbitmq
vb2008112 天前
基于AMQP协议模拟MQTT的发布 / 订阅主题功能
python·rabbitmq
csdn_aspnet2 天前
在 ASP.NET Core 中发布 RabbitMQ 消息
rabbitmq·.netcore
萧曵 丶2 天前
MQ 业务实际使用与问题处理详解
开发语言·kafka·消息队列·rabbitmq·rocketmq·mq
Noushiki2 天前
RabbitMQ 基础 学习笔记1
笔记·学习·rabbitmq
csdn_aspnet2 天前
在 ASP.NET Core 中使用(消费) RabbitMQ 消息
rabbitmq·.netcore
Noushiki2 天前
RabbitMQ 进阶 学习笔记2
笔记·学习·rabbitmq