rabbitmq在python中的发布订阅模式封装

publish/subscribe发布订阅模式:

  1. 消息产生者将消息放入交换机,交换机发布订阅把消息发送到所有消息队列中,对应消息队列的消费者拿到消息进行消费,代码的执行效率不高
  2. 相关场景:邮件群发,群聊天,广播(广告)
import threading
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):
        """订阅者的回调函数,可以在这里面做操作,比如释放库存等"""
        # ch.basic_ack(delivery_tag=method.delivery_tag)  # ack机制,
        print("邮箱", body.decode())

    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:队列名称
        """

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

        print("队列{}发送用户邮箱{}到MQ成功".format(queue_name, email))
        # 3. 关闭连接
        self.connection_close()

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

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

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

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


if __name__ == '__main__':
    obj1 = SingletonClass()
    print(id(obj1))
    # 发布消息
    obj1.this_publisher('2043232@qq.com')

    obj2 = SingletonClass()
    print(id(obj2))
    # 发布消息
    obj2.this_publisher('204323211111@qq.com')

  1. topic 主题模式(路由模式的一种),这种模式和路由模式差不多,exchange 也是通过 路由键 routing_key 来转发消息到指定的 queue 。 不同点是 routing_key 使用正则表达式支持模糊匹配,但匹配规则又与常规的正则表达式不同,比如“#”是匹配全部,“*”是匹配一个词
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RabbitMQ发布订阅模式是一种基于交换机(exchange)和队列(queue)的消息传递方式,它可以将消息广播给所有订阅了相关队列的消费者。下面是使用RabbitMQ实现发布订阅模式的基本步骤: 1. 创建一个连接和通道(channel)对象: ``` ConnectionFactory factory = new ConnectionFactory(); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); ``` 2. 声明一个交换机: ``` String exchangeName = "logs"; channel.exchangeDeclare(exchangeName, "fanout"); ``` 在声明交换机时,需要指定交换机的名称和类型。这里使用的是fanout类型,它会将所有消息广播给所有绑定到该交换机的队列。 3. 声明一个队列: ``` String queueName = channel.queueDeclare().getQueue(); ``` 在声明队列时,如果不指定队列名称,则RabbitMQ会自动生成一个队列名称,并返回给客户端。 4. 将队列绑定到交换机上: ``` channel.queueBind(queueName, exchangeName, ""); ``` 5. 发布消息到交换机上: ``` String message = "Hello World!"; channel.basicPublish(exchangeName, "", null, message.getBytes("UTF-8")); ``` 在发布消息时,需要指定交换机的名称和消息内容。由于是发布订阅模式,所以这里的路由键设置为"",表示消息将被发送到所有绑定到该交换机上的队列。 6. 接收消息: ``` Consumer consumer = new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { String message = new String(body, "UTF-8"); System.out.println("Received message: " + message); } }; channel.basicConsume(queueName, true, consumer); ``` 在接收消息时,需要创建一个消费者对象,并将其注册到队列。在这里,我们使用了一个DefaultConsumer类的子类来实现消费者对象,它会将收到的消息输出到控制台上。注意,在消费完消息后需要向RabbitMQ服务器发送确认消息,以便告诉服务器这条消息已经被处理完毕。 以上就是使用RabbitMQ实现发布订阅模式的基本步骤。在实际开发,我们可以根据具体的需求来调整这些步骤的顺序和参数设置,以实现不同的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值