为什么生产者需要一个binding_key进行主题交换?

时间:2019-04-28 05:38:01

标签: rabbitmq pika

实际上,我有两个关于主题交流的问题。

问题1:我认为只有队列和交换相互绑定是可以的,为什么生产者和交换需要绑定?

例如

# producer-->exchange--routing_key-->queues and customer
cat run.log |grep "routing_key_a" >> customer A;
cat run.log |grep "routing_key_b" >> customer B;

我将cat run.log用作消息生产者,并将grep "routing_key_a"用作routing_key,生产者产生了所有消息,并使用不同的routing_keys分发给了不同的客户A和B。这很容易理解,所以我不明白为什么我们仍然需要生产者和交换彼此绑定?

第二季度:我可以在生产者绑定中使用遗嘱卡进行交换(而不是在将遗嘱卡绑定至队列时使用遗留卡)吗?我曾经尝试过并且遇到了一些问题。

class RabbitmqServer:
    def __init__(self, host, port, nick_name="", topics=None, log_data=None):
        self.host = host
        self.port = port
        self.nick_name = nick_name
        self.connection = self._build_connection()
        self.channel = self._open_channel()
        self.exchange = self._declare_exchange()
        self.topics = topics if isinstance(topics, (list, tuple)) else []  # used to binding_key and routing_key
        self.log_data = log_data if log_data else []  # used to create log

    def _build_connection(self):
        return pika.BlockingConnection(
            pika.ConnectionParameters(host=self.host, port=self.port)
        )

    def _open_channel(self):
        return self.connection.channel()

    def _declare_exchange(self):
        return self.channel.exchange_declare(exchange="radius_logs", exchange_type="topic")

下面是生产者代码。

class SimpleLogger(RabbitmqServer):
    def __init__(self, *args, **kwargs):
        super(SimpleLogger, self).__init__(*args, **kwargs)

    def _publish(self, message):
        i = 1
        while True:
            log_index = i % len(self.log_data)
            log = self.log_data[log_index]
            _message = json.dumps(f"[{log}] "
                                  f"There is a piece log from radius server: {message}-No.-{i}")
            for topic in self.topics:
                self.channel.basic_publish(
                    exchange="radius_logs",
                    routing_key=topic,  
                    body=_message
                )
            print(f"producer with message: {_message}")
            i += 1
            time.sleep(0.15)

    def run(self):
        try:
            self._publish("1PMC")
        except Exception as e:
            print(f"Found exception: {e}")
            print("Exit..")
            self.connection.close()

下面是消费者。

class SimpleConsumer(RabbitmqServer):
    def __init__(self, *args, **kwargs):
        super(SimpleConsumer, self).__init__(*args, **kwargs)

    def _call_back(self, ch, method, properties, body):
        print(f"consumer with name = {self.nick_name} received {body}")
        ch.basic_ack(delivery_tag=method.delivery_tag)
        time.sleep(0.4)

    def _consume(self):
        queue = self.channel.queue_declare(queue="", exclusive=True)
        queue_name = queue.method.queue

        for t in self.topics:
            self.channel.queue_bind(exchange="radius_logs", queue=queue_name, routing_key=t)

        self.channel.basic_consume(on_message_callback=self._call_back, queue=queue_name, auto_ack=False)
        self.channel.start_consuming()

    def run(self):
        try:
            self._consume()
        except Exception as e:
            print(f"Found exception: {e}")
            print("Exit..")
            self.connection.close()

下面是运行代码。

if __name__ == "__main__":
    r_host = "10.0.7.176"
    r_port = 5672

    p1_binding_keys = ["*.orange.*", ]
    c1_binding_keys = ["*.orange.*", ]
    c2_binding_keys = ["*.*.rabbit", "lazy.#"]
    log_data = [
        "quick.orange.rabbit",          # will send to C1
        "lazy.orange.elephant",         # will send to C1
        "quick.orange.fox",             # will send to C1
        "lazy.brown.fox",               # will send to nobody
        "lazy.pink.rabbit",             # will send to nobody
        "quick.brown.fox",              # will send to nobody
        "orange",                       # will send to nobody
        "quick.orange.male.rabbit",     # will send to nobody
        "lazy.orange.male.rabbit",      # will send to nobody
    ]
    p1 = SimpleLogger(host=r_host, port=r_port, nick_name="P1", log_data=log_data, topics=p1_binding_keys)
    c1 = SimpleConsumer(host=r_host, port=r_port, nick_name="C1", topics=c1_binding_keys)
    c2 = SimpleConsumer(host=r_host, port=r_port, nick_name="C2", topics=c2_binding_keys)

    t1 = threading.Thread(target=p1.run)
    t2 = threading.Thread(target=c1.run)
    t3 = threading.Thread(target=c2.run)

    t1.start()
    t2.start()
    t3.start()

期望log_data是一个列表,用于创建日志内容,预期仅"quick.orange.rabbit", "lazy.orange.elephant", "lazy.brown.fox",发送给使用者C1,其余的将丢失。

实际上: 没有消息发送到C2,这与我们的预期相同。

 ⚙  rabitmq_demo # grep -i "C2" 5.log
 ✘ ⚙  rabitmq_demo 

但是,所有消息都发送到C1,这与预期的有所不同。为什么可以将诸如"quick.brown.fox",之类的消息发送到C1? 正如Question1所说,我真的对生产者进行交换的binding_key感到困惑,我认为不需要绑定生产者进行交换,对吗?可以向我解释这一点的人,非常感谢。

 rabitmq_demo # grep -i "C1" run.log
consumer with name = C1 received b'"[quick.orange.fox] There is a piece log from radius server: 1PMC-No.-2"'
consumer with name = C1 received b'"[lazy.brown.fox] There is a piece log from radius server: 1PMC-No.-3"'
consumer with name = C1 received b'"[lazy.pink.rabbit] There is a piece log from radius server: 1PMC-No.-4"'
consumer with name = C1 received b'"[quick.brown.fox] There is a piece log from radius server: 1PMC-No.-5"'
consumer with name = C1 received b'"[orange] There is a piece log from radius server: 1PMC-No.-6"'
consumer with name = C1 received b'"[quick.orange.male.rabbit] There is a piece log from radius server: 1PMC-No.-7"'
consumer with name = C1 received b'"[lazy.orange.male.rabbit] There is a piece log from radius server: 1PMC-No.-8"'
consumer with name = C1 received b'"[quick.orange.rabbit] There is a piece log from radius server: 1PMC-No.-9"'
consumer with name = C1 received b'"[lazy.orange.elephant] There is a piece log from radius server: 1PMC-No.-10"'
consumer with name = C1 received b'"[quick.orange.fox] There is a piece log from radius server: 1PMC-No.-11"'
consumer with name = C1 received b'"[lazy.brown.fox] There is a piece log from radius server: 1PMC-No.-12"'
consumer with name = C1 received b'"[lazy.pink.rabbit] There is a piece log from radius server: 1PMC-No.-13"'
consumer with name = C1 received b'"[quick.brown.fox] There is a piece log from radius server: 1PMC-No.-14"'
consumer with name = C1 received b'"[orange] There is a piece log from radius server: 1PMC-No.-15"'

0 个答案:

没有答案