3、RabbitMQ入门:核心概念与Hello World
消息队列这东西,说白了就是系统之间的「缓冲区」。我刚开始接触分布式系统时,总觉得加个中间件是多余。直到有一次线上服务因为突发流量直接被打挂,数据丢了整整两小时……嗯,从那以后,RabbitMQ就成了我工具箱里的常客。
今天咱们就聊聊RabbitMQ。它是目前用得最广的消息中间件之一,支持多种协议,性能稳定,社区活跃。我个人习惯把它比作「智能邮局」——你只管把信投进去,它保证送到收件人手里。
3.1 核心概念:Exchange、Queue、Binding
RabbitMQ有三个核心概念,你想想看,搞懂了它们,整个消息流转的脉络就清晰了。
3.1.1 Queue(队列)
队列就是消息的「收件箱」。生产者把消息发到队列里,消费者从队列里取消息。队列本质上是内存或磁盘上的一个数据结构,先进先出。
我在项目中遇到过一个问题:队列名称写错了,消费者一直收不到消息。排查了半天才发现是命名不一致。所以我的建议是——队列命名要有规范,比如 order.pay.success.queue 这种带业务前缀的格式。
3.1.2 Exchange(交换机)
交换机是消息的「路由器」。生产者不直接发消息到队列,而是发给交换机。交换机根据规则把消息路由到一个或多个队列。
RabbitMQ有四种交换机类型:
| 类型 | 路由规则 | 典型场景 |
|---|---|---|
| Direct | 完全匹配Routing Key | 点对点通信 |
| Topic | 通配符匹配Routing Key | 按主题订阅 |
| Fanout | 广播给所有绑定队列 | 发布/订阅 |
| Headers | 匹配消息头属性 | 复杂路由条件 |
说白了,Direct就是「一对一」,Fanout就是「一对多」,Topic就是「按规则匹配」。我个人用得最多的是Direct和Topic,简单够用。
3.1.3 Binding(绑定)
绑定就是把交换机和队列连接起来的「规则」。一个绑定包含三个要素:交换机名称、队列名称、Routing Key(路由键)。
举个例子:你有一个 order.exchange 交换机,一个 order.queue 队列,绑定时的Routing Key设为 order.created。那么只有Routing Key为 order.created 的消息才会被路由到这个队列。
核心关系图
生产者 → Exchange → (Binding + Routing Key) → Queue → 消费者
我曾经踩过一个坑:绑定关系配好了,但消息就是路由不过去。查了半天发现是Routing Key大小写不一致。RabbitMQ的Routing Key是区分大小写的,这一点务必注意。
3.2 安装与启动
安装RabbitMQ其实不复杂。我个人习惯用Docker,干净利落,不污染宿主机环境。
3.2.1 Docker方式(推荐)
# 拉取镜像
docker pull rabbitmq:3.12-management
# 启动容器
docker run -d --name rabbitmq \
-p 5672:5672 \
-p 15672:15672 \
rabbitmq:3.12-management
启动后,访问 http://localhost:15672,默认用户名密码都是 guest。5672是AMQP协议端口,15672是管理界面端口。
小提示:management后缀的镜像自带Web管理界面,调试时非常方便。我习惯在开发环境用这个版本,生产环境则用不带management的镜像,减少攻击面。
3.2.2 直接安装方式
如果你不想用Docker,也可以直接安装。以Ubuntu为例:
# 添加仓库
echo "deb https://packagecloud.io/rabbitmq/rabbitmq-server/ubuntu/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/rabbitmq.list
# 安装
sudo apt-get update
sudo apt-get install -y rabbitmq-server
# 启动
sudo systemctl start rabbitmq-server
sudo systemctl enable rabbitmq-server
安装完成后,记得启用管理插件:
sudo rabbitmq-plugins enable rabbitmq_management
注意:生产环境一定要修改默认密码!我曾经见过有人把guest/guest直接部署到线上,结果被扫到后用来发垃圾消息,整个IP被拉黑了。
3.3 Hello World示例
理论说完了,咱们动手写个最简单的例子。这个例子只有两个角色:一个生产者发消息,一个消费者收消息。
3.3.1 安装Python客户端
pip install pika
pika是RabbitMQ官方的Python客户端库,我用它写过不少生产级代码,稳定可靠。
3.3.2 生产者代码
import pika
# 建立连接
connection = pika.BlockingConnection(
pika.ConnectionParameters('localhost'))
channel = connection.channel()
# 声明队列
channel.queue_declare(queue='hello')
# 发送消息
channel.basic_publish(
exchange='',
routing_key='hello',
body='Hello World!')
print(" [x] 发送 'Hello World!'")
# 关闭连接
connection.close()
这里要注意:exchange='' 表示使用默认交换机。默认交换机会直接把消息路由到与 routing_key 同名的队列。说白了,这就是最简单的点对点模式。
3.3.3 消费者代码
import pika
# 建立连接
connection = pika.BlockingConnection(
pika.ConnectionParameters('localhost'))
channel = connection.channel()
# 声明队列(确保队列存在)
channel.queue_declare(queue='hello')
# 回调函数
def callback(ch, method, properties, body):
print(f" [x] 收到消息: {body.decode()}")
# 消费消息
channel.basic_consume(
queue='hello',
on_message_callback=callback,
auto_ack=True)
print(' [*] 等待消息。按Ctrl+C退出')
channel.start_consuming()
先运行消费者,再运行生产者。你会看到消费者打印出收到的消息。
运行结果:
消费者窗口显示:[x] 收到消息: Hello World!
3.3.4 代码解读
这个例子虽然简单,但包含了几个关键点:
- 连接与通道:Connection是TCP连接,Channel是虚拟连接。一个Connection可以创建多个Channel,节省资源。
- 队列声明:
queue_declare是幂等的,队列不存在就创建,存在就什么都不做。 - 消息发布:
basic_publish指定交换机、路由键和消息体。 - 消息消费:
basic_consume注册回调函数,有消息到达时自动调用。
我个人习惯在生产代码中把 auto_ack=False,然后手动确认消息。这样即使消费者在处理消息时崩溃,消息也不会丢失。这个咱们后面章节会详细讲。
3.4 本章小结
这一章我们聊了RabbitMQ的三个核心概念:Exchange负责路由,Queue负责存储,Binding负责连接。安装方面推荐Docker方式,简单快捷。最后的Hello World示例展示了最基础的消息收发流程。
你想想看,消息队列其实没那么神秘。它就是系统之间的「缓冲区」,帮我们解耦、削峰、异步。RabbitMQ作为老牌中间件,文档完善、社区活跃,值得花时间深入学习。
嗯,这一章就到这里。下一章咱们聊聊消息的持久化和确认机制——这两个是生产环境绝对不能忽视的细节。
公众号:蓝海资料掘金营,微信deep3321