python调用RabbitMQ
1、准备
想要python调用rabbitMQ需要安装pika
,所有需要提前安装好pika
包
# 全局
pip install pika;
# 如果用的anaconda的上面那个装不上可以试试这个?
conda install pika;
2、代码
2.1、生产者
生产者采用
direct
模式
import pika
USERNAME = 'admin' # 用户名
PASSWROD = 'admin' # 密码
HOST = '127.0.0.1' # rabbitMQ的IP
PORT = 5672 # 端口
WRITE_QUEUE='demo_write.queue' # 队列
WRITE_EXCHANGE='demo.exchange' # 交换机
ROUTING_KEY='demo' # routing-key
if __name__ == '__main__':
# 创建一个凭证
credentials=pika.PlainCredentials(username=USERNAME,password=PASSWROD)
# 创建一个连接
connection = pika.ConnectionParameters(host=HOST,port=PORT,credentials=credentials)
# 建立连接并获取一个通道,
# 此处采用阻塞连接(这个方式最简单了,但是对于生产者没啥区别)
channel = pika.BlockingConnection(connection).channel()
# 创建交换机和队列,如果没有就会自动创建
# 如果已经创建的与当前定义的不一样会**报错**
# 此处durable表示是是否持久化
channel.exchange_declare(exchange=WRITE_EXCHANGE,durable=True,exchange_type=ExchangeType.direct)
channel.queue_declare(queue=WRITE_QUEUE,durable=True)
# 绑定
# 如果队列或交换机不存在**报错**
channel.queue_bind(queue=WRITE_QUEUE,exchange=WRITE_EXCHANGE,routing_key=ROUTING_KEY)
message='{"data":"这里是我的消息"}'
# 进行生产
writeConnection.basic_publish(exchange=WRITE_EXCHANGE,routing_key=ROUTING_KEY,body=message)
2.2、消费者
消费者采用
basic
模式
import pika
USERNAME = 'admin' # 用户名
PASSWROD = 'admin' # 密码
HOST = '127.0.0.1' # rabbitMQ的IP
PORT = 5672 # 端口
READ_QUEUE='demo_read.queue' # 读取任务的队列名称(各个算法需要匹配对应的)
# 此时需要准备一个回调函数,参数不过多解释
def call_back(ch, method, properties, body):
# 获取一条消息(如果直接获取会是乱码)
message = str(body.decode('utf-8'))
# 处理逻辑
# 阿巴阿巴
# ack确认(确定接收成功后调用,不然消息会一直存在)
ch.basic_ack(delivery_tag=method.delivery_tag)
if __name__ == '__main__':
# 这些已经在上面解释过了
credentials=pika.PlainCredentials(username=USERNAME,password=PASSWROD)
connection = pika.ConnectionParameters(host=HOST,port=PORT,credentials=credentials)
# 此处采用阻塞连接
# 这个方式最简单了,当程序启动后会进行阻塞,当有消息来的时候就会进行消费,消费完成后在尝试获取下一个
channel = pika.BlockingConnection(connection).channel()
channel.queue_declare(queue=READ_QUEUE,durable=True)
# 消费设置
# 预读取数量
readConnection.basic_qos(prefetch_count=1)
# on_message_callback:回调函数名称
# auto_ack:是否自动ack
channel.basic_consume(queue=READ_QUEUE,on_message_callback=call_back,auto_ack=False)
# 开始消费
channel.start_consuming()
可能会出现的问题
A、104报错
关于运行一段时间报ConnectionResetError(104, ‘Connection reset by peer’)
错误的问题,可能原因可能二次调用时间太长断开或者连接建立时间过长断开。解决方法如下:
- 将写回专门开一个线程进行管理
- 写回时进行通道检测
- 如果可以添加
heartbeat = 0
如果在创建连接时
connection = pika.ConnectionParameters(host=HOST,port=PORT,credentials=credentials)
在添加heartbeat = 0
这个参数,仅仅编写上面的步骤1也大概率不会报错(大概率即我跑了5天都没崩)
import threading
import time
from queue import *
producer = getWriteChannel() # 这里是创建通道,只是封装了
writeQueue = Queue() # 生成一个队列
# 回调函数,用于接收请求主动执行
def call_back(ch, method, properties, body):
# 处理消息的代码
res = handler()
# 将结果放入队列
writeQueue.put(json)
# ack确认
ch.basic_ack(delivery_tag=method.delivery_tag)
# 线程逻辑
def writeBack(): # pika回写线程不安全,不能被其他线程干扰
while True: # 循环
if writeQueue.empty():
time.sleep(3) # 防止空轮训CPU100%
continue
val = writeQueue.get() # 获取消息
try:
global producer
# 判断通道是否关闭
if producer.is_closed:
# 关闭了就重新创建一个
producer = getWriteChannel() # 这里是创建通道,只是封装了
producer.basic_publish(exchange=WRITE_EXCHANGE,routing_key=ROUTING_KEY,body=val)
except Exception as e:
# 异常补偿,关闭后重新创建并将消息重新放回去
producer.close()
producer = getWriteChannel()
writeQueue.put(val)
# 开启线程
threading.Thread(target=writeBack,name=str(THREAD_COUNT)).start()
B、开启多个任务实际干活速度没有提上来?
抛开实际的运行瓶颈,资源数量,有可能是没有设置预读取数量。默认预读取数量时全部,这样会导致一个mq任务启动后直接读取全部消息而其他任务无消息可读。
# 就是这句话
readConnection.basic_qos(prefetch_count=1)
# 加在这段代码上面就可以了
# channel.basic_consume()
# channel.start_consuming()
本文作者:Ch1ee
本文链接:https://www.cnblogs.com/daimourentop/p/17605355.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步