- 在电商项目中,一但有秒杀活动,一瞬间进来的请求较多,假设一秒中进来的请求2万,但是数据库的并发只有2000,那么如果不做限制的话,db一下就会被打死或者导致很卡,那么就可以利用rabbitmq的ack机制prefetch_count(限制未处理消息的最大值)来平缓的取出数据来进行数据库的操作
import threading, time
import pika
class SingletonClass(object):
"""单例模式用来少创建连接"""
_singleton_lock = threading.Lock()
def __init__(self, username='baibing', password='123456', ip='47.111.87.61', port=5672, data={}):
"""__init__在new出来对象后实例化对象"""
self.credentials = pika.PlainCredentials(username, password)
self.connection = pika.BlockingConnection(
pika.ConnectionParameters(host=ip, port=port, credentials=self.credentials))
self.channel = self.connection.channel()
print('连接成功')
def __new__(cls):
"""__new__用来创建对象"""
if not hasattr(SingletonClass, "_instance"):
with SingletonClass._singleton_lock:
if not hasattr(SingletonClass, "_instance"):
SingletonClass._instance = super().__new__(cls)
return SingletonClass._instance
def callback(self, ch, method, properties, body):
"""订阅者的回调函数,可以在这里面做操作,比如释放库存等"""
print("邮箱", body.decode())
time.sleep(0.8)
ch.basic_ack(delivery_tag=method.delivery_tag)
def connection_close(self):
"""关闭连接"""
self.connection.close()
def consuming_start(self):
"""等待消息"""
self.channel.start_consuming()
def this_publisher(self, email, queue_name='HELLOP'):
"""发布者
email:消息
queue_name:队列名称
"""
self.channel.exchange_declare(exchange='python1', durable=True, exchange_type='topic')
self.channel.basic_publish(exchange='python1',
routing_key='#user#',
body=email,
properties=pika.BasicProperties(delivery_mode=2)
)
print("队列{}发送用户邮箱{}到MQ成功".format(queue_name, email))
self.connection_close()
def this_subscriber(self, queue_name='HELLOP', prefetch_count=10):
"""订阅者
queue_name:队列名称
prefetch_count:限制未处理消息的最大值,ack未开启时生效
"""
result = self.channel.queue_declare('', durable=True, exclusive=True)
self.channel.basic_qos(prefetch_count=5)
self.channel.exchange_declare(exchange='python1', durable=True, exchange_type='topic')
self.channel.queue_bind(exchange='python1', queue=result.method.queue, routing_key='#.anonymous.#')
self.channel.basic_consume(
result.method.queue,
self.callback,
auto_ack=False
)
self.consuming_start()
if __name__ == '__main__':
obj1 = SingletonClass()
print(id(obj1))
obj1.this_subscriber()