rabbitmq--pika
任务处理:请求数量太多,需要把消息临时放到某个地方
发布订阅,一旦发布消息,所有订阅者都会收到一条相同的消息
sh
# yum安装
安装配置epel源
rpm -ivh http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
$ yum -y install erlang
$ yum -y install rabbitmq-server
$ systemctl start rabbitmq-server
#docker 启动
docker pull rabbitmq:3.7.7-management
docker run --name mq -p 5672:5672 -p 15672:15672 -d rabbitmq:3.7.7-management
# 添加用户
sudo rabbitmqctl add_user rabbitmq mq123456
# 设置用户为administrator角色
sudo rabbitmqctl set_user_tags rabbitmq administrator
# 设置权限
sudo rabbitmqctl set_permissions -p "/" root ".*" ".*" ".*"
# 然后重启rabbiMQ服务
sudo systemctl restart rabbitmq-server
pika使用方法---> 1.3.2
https://www.rabbitmq.com/tutorials/tutorial-two-python
python
####################################生产者#####################################
import pika
credentials = pika.PlainCredentials("rabbitmq", "mq123456")
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.1.11', 5672, '/',credentials=credentials))
# 创建一个链接对象,对象中绑定rabbitmq的IP地址
channel = connection.channel() # 创建一个频道
channel.queue_declare(queue='name1') # 声明队列,存在忽略,没有则创建 生产者与消费者都设置下,防止报错
mq_messege="Hello World!"
channel.basic_publish(exchange='',
routing_key='name1', # 指定队列名称
body=mq_messege) # 往该队列中发送一个消息
print(mq_messege+"publish success")
connection.close()
hello world
单个消费者
python
# 单个消费者
import pika
credentials = pika.PlainCredentials("rabbitmq", "mq123456")
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.1.11', 5672, '/',credentials=credentials))
# 创建一个链接对象,对象中绑定rabbitmq的IP地址
channel = connection.channel() # 创建一个频道
channel.queue_declare(queue='name1') # 声明队列,存在忽略,没有则创建
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
ch.basic_ack(delivery_tag = method.delivery_tag) # 告诉服务端消息已取走,配合auto_ack=False使用
# channel.basic_consume('name1',callback,True)
channel.basic_consume(queue='name1', auto_ack=True, on_message_callback=callback) # 默认 auto_ack=True
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
C:\pythonProject1\venv\Scripts\python.exe C:/pythonProject1/jtest.py
[*] Waiting for messages. To exit press CTRL+C
[x] Received b'{Hello World!}'
[x] Received b'{Hello World!2}' #继续等待
work queues
多个消费者
再起一个消费者,同时消费,默认情况下 ,当有多个消费者启动时,mq将以轮询的形式被消费
批量发送 消息测试
python
"""
data.txt
{"goods_id":0,"product_id":9770,"sku_id":0}
{"goods_id":0,"product_id":9771,"sku_id":1}
{"goods_id":0,"product_id":9772,"sku_id":2}
{"goods_id":0,"product_id":9773,"sku_id":3}
"""
import pika
credentials = pika.PlainCredentials("rabbitmq", "mq123456")
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.1.11', 5672, '/',credentials=credentials))
# 创建一个链接对象,对象中绑定rabbitmq的IP地址
channel = connection.channel() # 创建一个频道
channel.queue_declare(queue='name1') # 声明队列,存在忽略,没有则创建
# 定义消息的headers
headers = {
'key1': 'value1',
'key2': 'value2'
}
with open('data.txt', 'r') as file:
for mq_messege in file:
channel.basic_publish(exchange='',
routing_key='name1', # 指定队列名称
body=mq_messege.strip()), # 往该队列中发送一些消息, 去掉换行符
properties=pika.BasicProperties(headers=headers)
print(mq_messege.strip()+"\n"+"publish success")
connection.close()
ack
防止客户端未处理消息,挂掉 auto_ack=False
python
# auto_ack=False时,rabbitmq里将出现unack消息 消费者,每次启动都会从头消费一次
import pika
credentials = pika.PlainCredentials("rabbitmq", "mq123456")
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.1.11', 5672, '/',credentials=credentials))
# 创建一个链接对象,对象中绑定rabbitmq的IP地址
channel = connection.channel() # 创建一个频道
channel.queue_declare(queue='name1') # 声明队列,存在忽略,没有则创建
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
channel.basic_consume(queue='name1', auto_ack=False, on_message_callback=callback) # 默认 auto_ack=True
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
告知server消息取走,防止客户端未处理消息,挂掉
python
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
# test_action # mq处理动作,处理失败时,将不会ack消息
ch.basic_ack(delivery_tag = method.delivery_tag) # 告诉服务端消息已取走,配合auto_ack=False使用
durable持久化
防止服务端挂掉,消息未持久化,丢失durable=True
python
# durable=True 默认False,不会改变已声明创建过的、非持久化的队列
channel.queue_declare(queue='name1',durable=True) # 声明队列,存在忽略,没有则创建
channel.basic_publish(exchange='',
routing_key="name1",
body=mq_message,
# make message persistent
properties=pika.BasicProperties(
delivery_mode = pika.DeliveryMode.Persistent
))
闲置消费
python
channel.basic_qos(prefetch_count=1)
python
channel.queue_declare(queue='name1') # 声明队列,存在忽略,没有则创建
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
# 闲置消费,避免消费者消费满,阻塞其他消费者消费
channel.basic_qos(prefetch_count=1)
channel.basic_consume(queue='name1', auto_ack=False, on_message_callback=callback) # 默认 auto_ack=True
全发布publish
exchange
订阅--消费者
每次运行,都会生成一个随机的queue,在rabbitmq页面上可以看到
exchange_type='fanout'
python
import pika
credentials = pika.PlainCredentials("rabbitmq", "mq123456")
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.1.11', 5672, '/',credentials=credentials))
# 创建一个链接对象,对象中绑定rabbitmq的IP地址
channel = connection.channel() # 创建一个频道
# exchange='log' exchange(秘书)的名称
# exchange_type='fanout',秘书工作方式将消息发送给所有的队列
channel.exchange_declare(exchange='logs', exchange_type='fanout')
# 随机生成一个队列
result = channel.queue_declare(queue='',exclusive=True)
queue_name = result.method.queue
# 让exchange和queque进行绑定
channel.queue_bind(exchange='logs', queue=queue_name)
def callback(ch, method, properties, body):
print(" 消费者 Received %r" % body)
channel.basic_consume(queue=queue_name, auto_ack=True, on_message_callback=callback) # 默认 auto_ack=True
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
发布--生产者
python
import pika
credentials = pika.PlainCredentials("rabbitmq", "mq123456")
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.1.11', 5672, '/',credentials=credentials))
# 创建一个链接对象,对象中绑定rabbitmq的IP地址
channel = connection.channel() # 创建一个频道
channel.exchange_declare(exchange='logs', exchange_type='fanout')
channel.basic_publish(exchange='logs',
routing_key='',
body='message')
channel.start_consuming()
如果上面的 订阅--消费者 代码运行了两个,那么每个订阅消费者都会收到 发布--生产者 的message
关键字发布(Routing)
exchange_type='direct'
routing_key='your key'
关键字分发
订阅--消费者
python
import pika
credentials = pika.PlainCredentials("rabbitmq", "mq123456")
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.1.11', 5672, '/',credentials=credentials))
# 创建一个链接对象,对象中绑定rabbitmq的IP地址
channel = connection.channel() # 创建一个频道
# exchange='log' exchange(秘书)的名称
# exchange_type='fanout',秘书工作方式将消息发送给所有的队列
channel.exchange_declare(exchange='logs', exchange_type='direct')
# 随机生成一个队列
result = channel.queue_declare(queue='',exclusive=True)
queue_name = result.method.queue
# 让exchange和queque进行绑定 # 另一个只有一个test绑定即可
channel.queue_bind(exchange='logs', queue=queue_name,routing_key='test')
channel.queue_bind(exchange='logs', queue=queue_name,routing_key='ceshi')
def callback(ch, method, properties, body):
print(" 消费者 Received %r" % body)
channel.basic_consume(queue=queue_name, auto_ack=True, on_message_callback=callback) # 默认 auto_ack=True
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
发布--生产者
python
import pika
credentials = pika.PlainCredentials("rabbitmq", "mq123456")
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.1.11', 5672, '/',credentials=credentials))
# 创建一个链接对象,对象中绑定rabbitmq的IP地址
channel = connection.channel() # 创建一个频道
channel.exchange_declare(exchange='logs', exchange_type='direct')
channel.basic_publish(exchange='logs',
routing_key='ceshi', # ceshi 一个收到,test都能收到
body='message')
channel.start_consuming()
模糊匹配 topic *
exchange_type='topic'
old.test -- exchange -- g1(关键字:old.*) 接收到 * 一个单词
-- g2(关键字:old.#) 接收到
old.test.ceshi -- exchange -- g1(关键字:old.*) 接收到
-- g2(关键字:old.#) 接收到 # 多个单词
订阅--消费者
python
import pika
credentials = pika.PlainCredentials("rabbitmq", "mq123456")
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.1.11', 5672, '/',credentials=credentials))
# 创建一个链接对象,对象中绑定rabbitmq的IP地址
channel = connection.channel() # 创建一个频道
# exchange='log' exchange(秘书)的名称
# exchange_type='fanout',秘书工作方式将消息发送给所有的队列
channel.exchange_declare(exchange='logs', exchange_type='topic')
# 随机生成一个队列
result = channel.queue_declare(queue='',exclusive=True)
queue_name = result.method.queue
# 让exchange和queque进行绑定 另起一个用 old.#
channel.queue_bind(exchange='logs', queue=queue_name,routing_key='old.*')
# 另起一个用 old.#
# channel.queue_bind(exchange='logs', queue=queue_name,routing_key='old.#')
def callback(ch, method, properties, body):
print(" 消费者 Received %r" % body)
channel.basic_consume(queue=queue_name, auto_ack=True, on_message_callback=callback) # 默认 auto_ack=True
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
发布--生产者
python
import pika
credentials = pika.PlainCredentials("rabbitmq", "mq123456")
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.1.11', 5672, '/',credentials=credentials))
# 创建一个链接对象,对象中绑定rabbitmq的IP地址
channel = connection.channel() # 创建一个频道
channel.exchange_declare(exchange='logs', exchange_type='topic')
channel.basic_publish(exchange='logs',
routing_key='old.test', # 再发一次 old.test.ceshi
body='message')
channel.start_consuming()