连接断了以后谁来恢复:连接、channel、exchange、队列、绑定、消费者,还有没发完的消息?不同客户端库差别很大。这篇用 pika 和 aio-pika 在同一个 broker 上做断线实验,看哪些被自动恢复,哪些要应用自己做。
消费者在线时收到: ['before'] $ rabbitmqctl close_connection "<pid>" "closed by operator" 之后 process_data_events: ConnectionClosedByBroker: (320, 'CONNECTION_FORCED - closed by operator') 连接状态: is_open=False;另一个连接又发了 "after" 一条,队列里现有 (ready, unacked) = (1, 0)——没有消费者了,消息停在队列里
pika 的 BlockingConnection 不会重连,连接被关后异常抛给调用者,所有对象都要应用重建。
broker 关闭用了 1.5 s,重新启动到可用用了 4.9 s broker 重新可用之后,消费者收到的第一条消息在 0.03 s 后(reconnect_interval=1 s) 发布端:确认成功 728 条,失败/超时 510 条(异常类型 ['ChannelInvalidStateError']);消费端:共收到 728 条,重复 0 条,redelivered=True 的 0 条 已确认发送但没收到的序号: [](共 0 条) 消费端相邻两条消息的最大间隔: 6.05 s(= 停机 + 重连期间的中断)
aio-pika 的 connect_robust 会按 reconnect_interval 重连,并把声明过的 exchange、队列、绑定和消费者重新声明。消费端无重复无丢失,持久消息一条不少;但发布端不一样——连接断开期间的 publish 直接失败(停机期间 510 次),robust 连接不会替你缓冲,应用要自己重试并考虑幂等。
另一个客户端删除队列 dq 之后,消费者收到: ['Cancel'](Basic.Cancel);channel 仍然开着: is_open=True 这种取消不会触发连接级的重连逻辑,客户端必须自己监听 cancel 并重新声明队列、重新订阅
broker 发 Basic.Cancel,连接和 channel 不受影响,客户端要自己监听并重新订阅。
排他队列(aio-pika 生成的名字 amq_…)重启后按原名 passive 声明: 存在(被 robust 客户端重新声明) durable 的 keepme 重启后: keepme(本来就在磁盘上)
恢复的是拓扑定义和订阅,不是数据:非持久队列在重启后是空的,未确认的发布结果不确定。