• Python操作rabbitmq系列(二):多个接收端消费消息


    今天,我们要逐步开始讨论rabbitmq稍微高级点的耍法了。了解这一步,对我们设计高并发的系统非常有用。当然,还可以使用kafka。不过还是算了,有几个硬性条件不支持,还是用rabbitmq吧。

    循环分发:

    启动一个发送端往队列发消息,此时启动多个接收端。发送的消息会对接收端一个一个挨着发送消息。如图:

    这就是默认情况下,多个接收端轮流消费消息。队列发送给消费端后,就立即删除。那么问题来了,当某个消费者在处理消息的时候,异常终止了怎么办?此时,我们更希望这样:若是那个消费者挂掉了,消息自动转给另一个消费者处理。

    幸好,rabbitmq就有效确认机制。消费者收到消息后,正常处理完成,此时才通知队列可以自由删除。那么问题又来了,消费者挂掉了连确认消息都发不出,该怎么办?rabbitmq维持了消费者的连接信息。消费者挂掉,与server的连接通道会关闭或tcp连接丢失。这时server知道了这个情况,就自动重发消息。

    这里还有个问题,就是server挂掉了怎么办?注意: durable=True。这个就是,当server挂了队列还存在。delivery_mode=2:server挂了消息还存在。若是保证消息不丢,这两个参数都要设置。

    发送端:

    import pika
    import sys

    connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
    channel = connection.channel()

    # durable:server挂了队列仍然存在
    channel.queue_declare(queue='task_queue', durable=True)

    # 使用默认的交换机发送消息。exchange为空就使用默认的。delivery_mode=2:使消息持久化。和队列名称绑定routing_key
    message = ' '.join(sys.argv[1:]) or "Hello World!"
    channel.basic_publish(exchange='',
    routing_key='task_queue',
    body=message,
    properties=pika.BasicProperties(
    delivery_mode=2,
    ))
    print(" [x] Sent %r" % message)
    connection.close()

    接收端:

    import pika
    import time

    connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
    channel = connection.channel()

    channel.queue_declare(queue='task_queue', durable=True)
    print(' [*] Waiting for messages. To exit press CTRL+C')


    def callback(ch, method, properties, body):
    print(" [x] Received %r" % body)
    time.sleep(body.count(b'.'))
    print(" [x] Done")
    # 手动对消息进行确认
    ch.basic_ack(delivery_tag=method.delivery_tag)


    # basic_consume:这个函数有no_ack参数。该参数默认为false。表示:需要对message进行确认。怎么理解:no设置成false,表示要确认
    channel.basic_consume(callback, queue='task_queue')
    channel.start_consuming()

    公平派遣:

    此刻,我们已经知道如何保证消息不丢,那么问题又来了。有的消费干得快,有的干得慢。这样分发消息,有的累死有的没事干。这个问题如何解决?

    rabbitmq已经考虑到了。那就是:那个干完了,通知给server,server就发送给那个。

    在上面的接收端的

    channel.basic_consume(callback, queue='task_queue')

    代码前加:

    channel.basic_qos(prefetch_count=1)

    即可

    现在,我们的消息都是一个给一个消费者。接下来,我们要讨论,向多个消费者发送相同的消息。

  • 相关阅读:
    go语言goroutine
    go语言接口
    go语言的map
    go语言切片
    go语言数组
    django的信号机制
    python redis 实现简单的消息订阅
    scrapy中使用selenium来爬取页面
    尝试用tornado部署django
    控制台输出太多导致项目启动过慢
  • 原文地址:https://www.cnblogs.com/zijiyanxi/p/7648062.html
Copyright © 2020-2023  润新知