mq使用

# mq
#!/usr/bin/env python3
import pika
# import threading
# from common.mq.mq_callback import CallBack
from common.utils.util import str_to_byte
from common.setting.config import DefaultConfig


class RabbitMq(object):
"""单例模式用来少创建连接"""
# 加锁,防止并发较高时,同时创建对象,导致创建多个对象
# _singleton_lock = threading.Lock()

def __init__(self, username=DefaultConfig.MQ_USERNAME, password=DefaultConfig.MQ_PASSWORD,
ip=DefaultConfig.MQ_HOSTNAME, port=DefaultConfig.MQ_PORT,
virtual_host=DefaultConfig.MQ_VirtualHost):
"""__init__在new出来对象后实例化对象"""
self.credentials = pika.PlainCredentials(username, password)
self.connection = pika.BlockingConnection(
pika.ConnectionParameters(host=ip, port=port, credentials=self.credentials,
virtual_host=virtual_host))
self.channel = self.connection.channel()

def __new__(cls):
"""__new__用来创建对象"""
# if not hasattr(RabbitMq, "_instance"):
# with RabbitMq._singleton_lock:
# if not hasattr(RabbitMq, "_instance"):
# RabbitMq._instance = super().__new__(cls)
if not hasattr(RabbitMq, "_instance"):
# with RabbitMq._singleton_lock:
# if not hasattr(RabbitMq, "_instance"):
RabbitMq._instance = super().__new__(cls)
return RabbitMq._instance

def producer(self, data, delivery_mode=2, exchange=DefaultConfig.MQ_EXCHANGE, routing_key=DefaultConfig.MQ_QUEUE):
self.channel.queue_declare(
queue=DefaultConfig.MQ_QUEUE,
durable=True
)
self.channel.basic_publish(
exchange=exchange,
routing_key=routing_key,
body=str_to_byte(data),
properties=pika.BasicProperties(
delivery_mode=delivery_mode # 使队列中的消息持久化
)
)

def consumer(self, callback, auto_ack=False, queue=DefaultConfig.MQ_QUEUE):
self.channel.basic_qos(prefetch_count=1) # 处理完当前这条信息再发送下一条消息,公平消息机制,这样就不会因为某些处理速度慢的机器一直收到消息而处理不完
result = self.channel.queue_declare(queue, durable=True, exclusive=False, auto_delete=False)
# # 声明exchange,由exchange指定消息在哪个队列传递,如不存在,则创建。durable = True 代表exchange持久化存储,False 非持久化存储
# self.channel.exchange_declare(exchange=DefaultConfig.MQ_Exchange, durable=True, exchange_type=DefaultConfig.MQ_Exchange_type)
# # 绑定exchange和队列 exchange 使我们能够确切地指定消息应该到哪个队列去
# self.channel.queue_bind(exchange=DefaultConfig.MQ_Exchange, queue=result.method.queue)
self.channel.basic_consume( # 消费信息
on_message_callback=callback, # 如果收到消息,就调用CALLBACK函数来处理消息
# 选择管道
queue=result.method.queue,
auto_ack=auto_ack)

self.channel.start_consuming()

def get_queue_message_count(self, queue):
queue_result = self.channel.queue_declare(queue=queue, durable=True)
return queue_result.method.message_count

def this_publisher(self, email, queue_name=''):
"""发布者
email:消息
queue_name:队列名称
"""

# 1、创建一个名为python-test的交换机 durable=True 代表exchange持久化存储
self.channel.exchange_declare(exchange='python1', durable=True, exchange_type='topic')
# self.channel.queue_declare(queue=queue_name)
# 2、订阅发布模式,向名为python-test的交换机中插入用户邮箱地址email,delivery_mode = 2 声明消息在队列中持久化,delivery_mod = 1 消息非持久化
self.channel.basic_publish(exchange='python1',
routing_key='asdsfdf.anonymous.sfdfa',
body=email,
properties=pika.BasicProperties(delivery_mode=2)
)

def this_subscriber(self, callback, queue_name='', prefetch_count=10):
"""订阅者
queue_name:队列名称
prefetch_count:限制未处理消息的最大值,ack未开启时生效
"""
# 创建临时队列,队列名传空字符,consumer关闭后,队列自动删除
result = self.channel.queue_declare('', durable=True, exclusive=True)

# 声明exchange,由exchange指定消息在哪个队列传递,如不存在,则创建。durable = True 代表exchange持久化存储,False 非持久化存储
self.channel.exchange_declare(exchange='python1', durable=True, exchange_type='topic')

# 绑定exchange和队列 exchange 使我们能够确切地指定消息应该到哪个队列去
self.channel.queue_bind(exchange='python1', queue=result.method.queue, routing_key='#.anonymous.#')

self.channel.basic_consume(
result.method.queue,
callback, # 回调地址(函数)
auto_ack=False # 设置成 False,在调用callback函数时,未收到确认标识,消息会重回队列。True,无论调用callback成功与否,消息都被消费掉
)
# 等待消息
self.channel.start_consuming()

def connection_close(self):
self.connection.close()


if __name__ == '__main__':
def func(ch, method, properties, body):
print(body)
ch.basic_ack(delivery_tag=method.delivery_tag) # 向生产者发送确认消息
# 调用后就停止
ch.stop_consuming()
mq = RabbitMq()
for i in range(mq.get_queue_message_count(DefaultConfig.MQ_QUEUE)):
mq.consumer(func)
mq.connection_close()

ma_call_back
import json

from app import db

class CallBack(object):

@staticmethod
def egg_stop_callback(ch, method, properties, body):
# print('body', body) # 消息内容
data = byte_to_str(body)
ch.basic_ack(delivery_tag=method.delivery_tag) # 向生产者发送确认消息
# 调用后就停止
ch.stop_consuming()

# 调用后不停止
@staticmethod
def egg_callback(ch, method, properties, body):
# print('body', body) # 消息内容
ch.basic_ack(delivery_tag=method.delivery_tag) # 向生产者发送确认消息
data = byte_to_str(body)
print(data)



posted @ 2022-04-12 10:11  wyz_1  阅读(98)  评论(0编辑  收藏  举报