目录
- [简介](#简介)
- [安装与配置](#安装与配置)
- [基本概念](#基本概念)
- [发布/订阅模式](#发布-订阅模式)
- [工作队列模式](#工作队列模式)
- [路由模式](#路由模式)
- [主题模式](#主题模式)
- [RPC 模式](#rpc-模式)
- [总结](#总结)
简介
RabbitMQ 是一个开源的消息代理和队列服务器,实现了 AMQP 1.0 协议。它提供了一种可靠的、异步的通信方式。
安装与配置
安装 RabbitMQ
Ubuntu
```bash
sudo apt-get update
sudo apt-get install rabbitmq-server
```
macOS (使用 Homebrew)
```bash
brew install rabbitmq
```
启动服务
```bash
rabbitmq-server
```
开启管理插件
```bash
rabbitmq-plugins enable rabbitmq_management
```
访问管理界面
- 浏览器访问: http://localhost:15672/
- 默认账号密码: guest/guest
基本概念
- Exchange - 交换机,接收和发送消息到队列。
- Queue - 队列,用于存储消息直到它们被消费。
- Binding - 绑定,定义了消息从交换机到队列的路由规则。
- Routing Key - 路由键,用于将消息发送到特定的队列。
发布/订阅模式
创建 Exchange 和 Queue
```python
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='logs', exchange_type='fanout')
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue
channel.queue_bind(exchange='logs', queue=queue_name)
```
发送消息
```python
channel.basic_publish(
exchange='logs',
routing_key='',
body='Hello, world!'
)
connection.close()
```
接收消息
```python
def callback(ch, method, properties, body):
print(f" [x] Received {body}")
channel.basic_consume(
queue=queue_name,
on_message_callback=callback,
auto_ack=True
)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
```
工作队列模式
创建 Queue
```python
channel.queue_declare(queue='task_queue', durable=True)
```
发送消息
```python
message = "A message to process"
channel.basic_publish(
exchange='',
routing_key='task_queue',
body=message,
properties=pika.BasicProperties(
delivery_mode=pika.spec.PERSISTENT_DELIVERY_MODE
)
)
```
接收消息
```python
def callback(ch, method, properties, body):
print(f" [x] Received {body}")
# Simulate work
time.sleep(body.count(b'.'))
print(" [x] Done")
ch.basic_ack(delivery_tag=method.delivery_tag)
channel.basic_qos(prefetch_count=1)
channel.basic_consume(
queue='task_queue',
on_message_callback=callback
)
channel.start_consuming()
```
路由模式
创建 Exchange 和 Queue
```python
channel.exchange_declare(exchange='direct_logs', exchange_type='direct')
severities = ['info', 'warning', 'error']
for severity in severities:
queue_name = f"{severity}_queue"
channel.queue_declare(queue=queue_name)
channel.queue_bind(
exchange='direct_logs',
queue=queue_name,
routing_key=severity
)
```
发送消息
```python
message = "An info message"
channel.basic_publish(
exchange='direct_logs',
routing_key='info',
body=message
)
```
接收消息
```python
def callback(ch, method, properties, body):
print(f" [x] Received {body}")
channel.basic_consume(
queue='info_queue',
on_message_callback=callback,
auto_ack=True
)
channel.start_consuming()
```
主题模式
创建 Exchange 和 Queue
```python
channel.exchange_declare(exchange='topic_logs', exchange_type='topic')
binding_keys = ['#', 'kern.*', '*.critical']
for binding_key in binding_keys:
queue_name = f"{binding_key.replace('.', '_').replace('#', '_hash_')}_queue"
channel.queue_declare(queue=queue_name)
channel.queue_bind(
exchange='topic_logs',
queue=queue_name,
routing_key=binding_key
)
```
发送消息
```python
message = "A critical kernel message"
channel.basic_publish(
exchange='topic_logs',
routing_key='kern.critical',
body=message
)
```
接收消息
```python
def callback(ch, method, properties, body):
print(f" [x] Received {body}")
channel.basic_consume(
queue='kern__critical_queue',
on_message_callback=callback,
auto_ack=True
)
channel.start_consuming()
```
RPC 模式
请求端
```python
response = None
corr_id = str(uuid.uuid4())
def on_response(ch, method, props, body):
global response
if corr_id == props.correlation_id:
response = body
channel.basic_consume(
queue=callback_queue,
on_message_callback=on_response,
auto_ack=True
)
channel.basic_publish(
exchange='',
routing_key='rpc_queue',
properties=pika.BasicProperties(
reply_to=callback_queue,
correlation_id=corr_id
),
body=str(n)
)
while response is None:
connection.process_data_events()
result = int(response)
```
服务端
```python
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
def on_request(ch, method, props, body):
n = int(body)
print(f" [.] fib({n})")
response = fib(n)
ch.basic_publish(
exchange='',
routing_key=props.reply_to,
properties=pika.BasicProperties(correlation_id=props.correlation_id),
body=str(response)
)
ch.basic_ack(delivery_tag=method.delivery_tag)
channel.basic_qos(prefetch_count=1)
channel.basic_consume(
queue='rpc_queue',
on_message_callback=on_request
)
print(" [x] Awaiting RPC requests")
channel.start_consuming()