【问题标题】:Python pika - Publishing to non-existing exchange does not raise exceptionPython pika - 发布到不存在的交换不会引发异常
【发布时间】:2019-06-12 04:00:09
【问题描述】:

根据https://www.rabbitmq.com/amqp-0-9-1-reference.html#basic.publish发布时,

如果指定了交换名称,并且该交换不存在,服务器将引发通道异常。

使用 pika,这只会在第二次通过同一渠道将消息发送到缺少的交换器时发生:

(env36x64) C:\Program Files\RabbitMQ Server\rabbitmq_server-3.7.4\sbin>rabbitmqctl.bat list_exchanges name
Listing exchanges for vhost / ...
amq.fanout
amq.match
amq.headers

amq.rabbitmq.trace
amq.topic
amq.direct

(env36x64) C:\Program Files\RabbitMQ Server\rabbitmq_server-3.7.4\sbin>python
Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 17:00:18) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> import pika
>>> creds = pika.PlainCredentials('user', 'passw')
>>> params = pika.ConnectionParameters(host='ms7', port=5672, credentials=creds)
>>> conn = pika.BlockingConnection(params)
>>> ch = conn.channel()
>>> ch.basic_publish(exchange='invalid', routing_key='', body='hello')
>>> # No error. Not expected
>>> # Second attempt does raise exception, as expected
>>> ch.basic_publish(exchange='invalid', routing_key='', body='hello')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\Administrator\Documents\env36x64\lib\site-packages\pika\adapters\blocking_connection.py", line 2239, in basic_publish
    self._flush_output()
  File "C:\Users\Administrator\Documents\env36x64\lib\site-packages\pika\adapters\blocking_connection.py", line 1331, in _flush_output
    raise self._closing_reason  # pylint: disable=E0702
pika.exceptions.ChannelClosedByBroker: (404, "NOT_FOUND - no exchange 'invalid' in vhost '/'")
  • 鼠兔 1.0.1
  • RabbitMQ 服务器 3.7.4
  • 二郎20.3
  • Python 3.6.5

【问题讨论】:

    标签: python-3.x rabbitmq pika


    【解决方案1】:

    如果您使用 Wireshark 进行数据包捕获,它会解释您所看到的行为。从 RabbitMQ 发送到您的测试应用程序的Channel.Close异步,因此您的第二个basic_publish 调用在收到第一个Channel.Close 之前执行。 RabbitMQ 或 Pika 都没有错误。


    注意:RabbitMQ 团队会监控 rabbitmq-users mailing list,并且有时只回答 StackOverflow 上的问题。

    【讨论】:

    • 有办法解决这个问题。如果您在发布前启用交付确认,它应该会在发布时出错。 ch.confirm_delivery()
    • 确认也是异步的。 Pika BlockingConnection 同步等待确认,因此这适用于此用例,但一般请注意,确认也是异步的。
    • 发送确认会告诉我消息是否进入队列,但我很想知道消息是否进入交换。我使用 SelectConnection 在后台线程中运行 ioloop 测试了异步代码(以解决阻塞问题),但是从主线程关闭连接时得到了一些意想不到的结果,因为 pika 并不是真正的线程安全。现在我正在测试支持多线程的rabbitpy
    猜你喜欢
    • 1970-01-01
    • 2016-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多