配置环境变量
sudo vi /etc/profile
//加入以下两行
export RABBIT_HOME=/usr/local/Cellar/rabbitmq/3.7.4
export PATH=$PATH:$RABBIT_HOME/sbin
// 立即生效
source /etc/profile
常用命令
服务启动/关闭
- 后台启动:
rabbitmq-server -detached
- 关闭服务:
rabbitmqctl stop
用户管理
- 添加用户:
rabbitmqctl add_user username passwoord
- 删除用户:
rabbitmqctl delete_user username
- 修改用户密码:
rabbitmqctl change_password username password
- 查看所有用户:
rabbitmqctl list_users
- 设置用户角色:
rabbitmqctl set_user_tags username tag #tag分别有:adminstrator, monitoring, management, policymaker
插件管理
- 开启插件:
rabbitmq-plugins enable plugin_name
- 关闭插件:
rabbitmq-plugins disable plugin_name
- 查看插件状态:
rabbitmq-plugins list
查看其他
- 查看状态:
rabbitmqctl statu
- 查看所有交换机:
rabbitmqctl list_exchanges
- 查看队列绑定情况:
rabbitmqctl list_bindings
可视化
- 启动插件:
rabbitmq-plugins enable rabbitmq_management
- 地址:
http://localhost:15672
工作队列
生产者
import sys
import pika
# 连接rabbit,创建信道
credentials = pika.PlainCredentials('guest', 'guest')
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, '/', credentials))
channel = connection.channel()
# 声明消息队列,消息将在这个队列中进行传递。如果将消息发送到不存在的队列,rabbitmq将会自动清除这些消息。如果队列不存在,则创建
channel.queue_declare(queue='task_queue',
durable=True) # durable 队列持久化
# 向队列插入数值 routing_key是队列名 body是要插入的内容
message = ".".join(sys.argv[1:] or "Hello World!")
# 向通道发布消息
channel.basic_publish(
exchange='', # 交换机
routing_key='task_queue',
body=message,
properties=pika.BasicProperties(
delivery_mode=2, # make message persistent 使消息持久
)
)
print(f"[x] Sent {message}")
connection.close()
消费者
import time
import pika
credentials = pika.PlainCredentials('guest', 'guest')
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, '/', credentials))
channel = connection.channel()
# 声明消息队列
channel.queue_declare(
queue='task_queue',
durable=True # durable 队列持久化
)
# 定义一个回调函数来处理,这边的回调函数就是将信息打印出来。
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
time.sleep(3)
print(" [x] Done")
# 告诉RabbitMQ,再同一时刻,不要发送超过1条消息给一个工作者(worker),直到它已经处理了上一条消息并且作出了响应。这样,RabbitMQ就会把消息分发给下一个空闲的工作者(worker)。
channel.basic_qos(prefetch_count=2)
# 告诉rabbitmq使用callback来接收信息
channel.basic_consume(on_message_callback=callback,
queue='task_queue',
# auto_ack=False # 之前是叫no_ack : auto_ack=True的时候, 消费者挂掉会丢失消息, 并且prefetch_count的设定会无效
)
print(' [*] Waiting for messages. To exit press CTRL+C')
# 开始接收信息,并进入阻塞状态,队列里有信息才会调用callback进行处理。按ctrl+c退出。
channel.start_consuming()
扇形交换机 - 发布/订阅
生产者
"""
发布/订阅
1. 声明临时队列
2. 交换机绑定队列
3. 两个消费者同时消费
"""
import sys
import pika
# 文档: http://rabbitmq.mr-ping.com/tutorials_with_python/[3]Publish_Subscribe.html
credentials = pika.PlainCredentials('guest', 'guest')
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, '/', credentials))
channel = connection.channel()
# 声明交换机, 类型是扇形交换机(广播)
channel.exchange_declare(exchange='logs', exchange_type='fanout')
# 向队列插入数值 routing_key是队列名 body是要插入的内容
message = ".".join(sys.argv[1:] or "Hello World!")
channel.basic_publish(
exchange='logs', # 交换机
routing_key='',
body=message,
)
print(f"[x] Sent {message}")
connection.close()
消费者
"""
发布/订阅
1. 声明临时队列
2. 交换机绑定队列
3. 两个消费者同时消费
"""
import time
import pika
credentials = pika.PlainCredentials('guest', 'guest')
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, '/', credentials))
channel = connection.channel()
# 声明交换机, 类型是扇形交换机(广播)
channel.exchange_declare(exchange='logs', exchange_type='fanout')
# 临时队列. exclusive: 当与消费者(consumer)断开连接的时候,这个队列应当被立即删除。
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue
# 绑定交换机和队列
channel.queue_bind(exchange='logs', queue=queue_name)
print(' [*] Waiting for messages. To exit press CTRL+C')
# 定义一个回调函数来处理,这边的回调函数就是将信息打印出来。
def callback(ch, method, properties, body):
print(" [x] %r" % body)
channel.basic_consume(on_message_callback=callback,
queue=queue_name,
auto_ack=True)
# 开始接收信息,并进入阻塞状态,队列里有信息才会调用callback进行处理。按ctrl+c退出。
channel.start_consuming()
直连交换机 - 路由
生产者
import sys
import pika
# 文档: http://rabbitmq.mr-ping.com/tutorials_with_python/[4]Routing.html
credentials = pika.PlainCredentials('guest', 'guest')
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, '/', credentials))
channel = connection.channel()
# 声明交换机, 类型是直连交换机
channel.exchange_declare(exchange='direct_logs', exchange_type='direct')
severity = sys.argv[1] if len(sys.argv) > 1 else 'info'
# 向队列插入数值 routing_key是队列名 body是要插入的内容
message = ".".join(sys.argv[1:] or "Hello World!")
channel.basic_publish(
exchange='direct_logs', # 交换机
routing_key=severity,
body=message,
)
print(f"[x] Sent {severity, message}")
connection.close()
消费者
import pika
import sys
credentials = pika.PlainCredentials('guest', 'guest')
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, '/', credentials))
channel = connection.channel()
# 声明交换机, 类型是扇形交换机
channel.exchange_declare(exchange='direct_logs', exchange_type='direct')
# 临时队列. exclusive: 当与消费者(consumer)断开连接的时候,这个队列应当被立即删除。
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue
severities = sys.argv[1:]
if not severities:
sys.stderr.write("Usage: %s [info] [warning] [error]\n" % sys.argv[0])
sys.exit(1)
for severity in severities:
channel.queue_bind(
exchange='direct_logs',
queue=queue_name,
routing_key=severity
)
print(' [*] Waiting for messages. To exit press CTRL+C')
# 定义一个回调函数来处理,这边的回调函数就是将信息打印出来。
def callback(ch, method, properties, body):
print(" [x] %r" % body)
channel.basic_consume(on_message_callback=callback,
queue=queue_name,
auto_ack=True)
# 开始接收信息,并进入阻塞状态,队列里有信息才会调用callback进行处理。按ctrl+c退出。
channel.start_consuming()
主题交换机
生产者
import sys
import pika
# 文档: http://rabbitmq.mr-ping.com/tutorials_with_python/[5]Routing.html
credentials = pika.PlainCredentials('guest', 'guest')
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, '/', credentials))
channel = connection.channel()
# 声明交换机, 类型是直连交换机
channel.exchange_declare(exchange='topic_logs', exchange_type='topic')
routing_key = sys.argv[1] if len(sys.argv) > 2 else 'anonymous.info'
# 向队列插入数值 routing_key是队列名 body是要插入的内容
message = ".".join(sys.argv[2:] or "Hello World!")
channel.basic_publish(exchange='topic_logs', # 交换机
routing_key=routing_key,
body=message)
print(f" [x] Sent {routing_key, message}")
connection.close()
消费者
import pika
import sys
credentials = pika.PlainCredentials('guest', 'guest')
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, '/', credentials))
channel = connection.channel()
# 声明交换机, 类型是扇形交换机
channel.exchange_declare(exchange='topic_logs', exchange_type='topic')
# 临时队列. exclusive: 当与消费者(consumer)断开连接的时候,这个队列应当被立即删除。
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue
binding_keys = sys.argv[1:]
if not binding_keys:
sys.stderr.write("Usage: %s [binding_key]...\n" % sys.argv[0])
sys.exit(1)
for binding_key in binding_keys:
channel.queue_bind(
exchange='topic_logs',
queue=queue_name,
routing_key=binding_key
)
print(' [*] Waiting for messages. To exit press CTRL+C')
# 定义一个回调函数来处理,这边的回调函数就是将信息打印出来。
def callback(ch, method, properties, body):
print(" [x] %r:%r" % (method.routing_key, body))
channel.basic_consume(on_message_callback=callback,
queue=queue_name,
auto_ack=True)
# 开始接收信息,并进入阻塞状态,队列里有信息才会调用callback进行处理。按ctrl+c退出。
channel.start_consuming()
参考:https://www.rabbitmq.com/tutorials/tutorial-five-python.html