python消息队列RabbitMQ
tags:
- python3
- python基础
categories:
- RabbitMQ
- 消息队列
- RPC实现
文章目录
一、消息队列RabbitMQ介绍
- 消息队列提出:我们知道在Python中有
- 线程QUEUE:threading QUEUE 同一进程下线程之间数据的交互
- 进程QUEUE:父进程与子进程进行交互,或者同属于同一父进程下多个子进程进行交互
- 如果两个独立的进程(可以是不同语言写的)想要交互通信,或者两台机器之间想要进行通信。
消息队列有RabbitMQ(比较火),ZeroMQ,ActiveMQ … - RabbitMq 是实现了高级消息队列协议(AMQP)的开源消息代理中间件。消息队列是一种应用程序对应用程序的通行方式,应用程序通过写消息,将消息传递于队列,由另一应用程序读取完成通信。而作为中间件的 RabbitMq 无疑是目前最流行的消息队列之一。
- RabbitMq 应用场景广泛:
- 系统的高可用:日常生活当中各种商城秒杀,高流量,高并发的场景。当服务器接收到如此大量请求处理业务时,有宕机的风险。某些业务可能极其复杂,但这部分不是高时效性,不需要立即反馈给用户,我们可以将这部分处理请求抛给队列,让程序后置去处理,减轻服务器在高并发场景下的压力。
- 分布式系统,集成系统,子系统之间的对接,以及架构设计中常常需要考虑消息队列的应用。
1. 1 RabbitMQ安装
- erlang 语言开发的。所以安装RabbitMQ之前先安装erlang
- 到erlang官网: https://www.erlang.org/downloads 下载 OTP 22.2 Windows 64-bit Binary File
- 安装配置erlang:加入环境变量D:\Erlang\bin
- 输入cmd,再输入erl,看到版本号就说明erlang安装成功了。
- erl和RabbitMQ版本对应关系:https://www.rabbitmq.com/which-erlang.html
- RabbitMQ官网:https://www.rabbitmq.com/
- 安装好之后。进入安装目录D:\RabbitMQ\rabbitmq_server-3.7.24\sbin
- 运行命令:rabbitmq-plugins enable rabbitmq_management
- 然后打开浏览器,输入localhost:15672 输入默认账号和密码guest和guest。登录成功
rabbitmqct1.bat list_queues #查看队列
1.2 RabbitMQ基本使用
- python连接RabbitMQ的模块有:pika, Celery,Haigha(官网给出)
- RabbitMQ也支持其他种类的语言。(官网可查)
- 安装python模块pika: pip install pika
- 官方教程网址:https://www.rabbitmq.com/getstarted.html
- 实现最简单的队列通信
#product.py服务器生产者
import pika
'''
连接参数 host,port(默认5672),virtual_host,credentials(验证)
credentials = pika.PlainCredentials('shampoo', '123456') # mq用户名和密码验证
虚拟队列需要指定参数 virtual_host,如果是默认的可以不填。
'''
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
# 声明queue(给队列起名)
channel.queue_declare(queue='hello')
# n RabbitMQ a message can never be sent directly to the queue, it always needs to go through an exchange.
# 基本发送
channel.basic_publish(exchange='', # 图中的X,不用深究。知道默认为''就行
routing_key='hello', # queue名字
body='Hello World!') # 发送的内容
print("消息发送完毕")
connection.close()
# consumer.py 客户端消费者
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
# 这里在声明一次hello的原因。如果消费者先运行,hello生产者还不存在就会报错。
# 如果确定服务器端先启动,队列名确定叫hello。下面也可以不写(推荐写上呀!!!兄弟)
channel.queue_declare(queue='hello')
def callback(ch, method, properties, body):
'''
:param ch: 管道的内存对象
:param method:
:param properties:
:param body:
:return:
'''
import time
print("开始")
time.sleep(10)
print("Received %r" % body)
ch.basic_ack(delivery_tag=method.delivery_tag)
# 消费消息,如果收到消息就调用callback处理消息。从hello队列中收消息。
# auto_ack 自动确认,消息处理完给服务器发消息
channel.basic_consume('hello', callback, True)
print('等待接收消息,关闭按CTRL+C')
channel.start_consuming()
1.3 RabbitMq 常用设置
- 远程连接rabbitmq server的话,需要配置权限
- 首先在rabbitmq server上创建一个用户
- 同时还要配置权限,允许从外面访问
# 创建账号
rabbitmqctl add_user admin 123456
# 设置用户角色
rabbitmqctl set_user_tags admin administrator
# 设置用户权限
rabbitmqctl set_permissions -p "/“oldlu” .""."".*"
# 设置完成后可以查看当前用户和角色(需要开启服务)
rabbitmqctl list_users
- 轮询处理消息。假如开启多个消费者,生产者发送消息后,先发送到先启动的消费者以此循环。
- 如果消费者处理消息时宕机啦。消费者(consumer)调用callback函数时,会存在处理消息失败的风险,如果处理失败,则消息丢失。但是也可以选择消费者处理失败时,将消息回退给 rabbitmq ,重新再被消费者消费,这个时候需要设置确认标识。
- auto_ack 自动确认False情况(默认) channel.basic_consume(‘hello’, callback, True)
- ch.basic_ack(delivery_tag=method.delivery_tag) 手动确认。如果不确认配置了False,任务只要有客户端它会一直重复做下去。
- 如果服务器生产者宕机的话,如果没有持久化,那肯定全都不见了。
- 如果Rabbit只管按顺序把消息发到各个消费者身上,不考虑消费者负载的话,很可能出现,一个机器配置不高的消费者那里堆积了很多消息处理不完,同时配置高的消费者却一直很轻松。为解决此问题,可以在各个消费者端,配置perfetch=1,意思就是告诉RabbitMQ在我这个消费者当前消息还没处理完的时候就不要再给我发新消息了。解决方法:客户端加入下面一句
# 客户端最多存一条
channel.basic_qos(prefetch_count=1)
二、RabbitMq 持久化
MQ默认建立的是临时 queue 和 exchange,如果不声明持久化,一旦 rabbitmq 挂掉,queue、exchange 将会全部丢失。所以我们一般在创建 queue 或者 exchange 的时候会声明持久化。客户端和服务器端都需要设置。
- queue 队列持久化