易陆发现互联网技术论坛

 找回密码
 开始注册
查看: 4081|回复: 3
收起左侧

error: [Errno 104] Connection reset by peer nova server-list结果结算节点down

[复制链接]
发表于 2021-6-17 15:47:38 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?开始注册

x
2021-06-17 15:38:54.687 25 ERROR oslo.messaging._drivers.impl_rabbit [req-16c1bbd6-5bb1-4c14-a05f-8dbbd6c709b0 - - - - -] [7c38fc9d-5a2e-482e-8f51-fd364d05359d] AMQP server on 10.160.77.3:5672 is unreachable: [Errno 104] Connection reset by peer. Trying again in 1 seconds.: error: [Errno 104] Connection reset by peer
/ X' G8 V, d; |; R" Z& O1 R+ c2021-06-17 15:38:55.412 26 INFO oslo.messaging._drivers.impl_rabbit [-] A recoverable connection/channel error occurred, trying to reconnect: [Errno 104] Connection reset by peer$ u! h2 F6 D; H3 y4 @8 p
2021-06-17 15:38:55.708 25 INFO oslo.messaging._drivers.impl_rabbit [req-16c1bbd6-5bb1-4c14-a05f-8dbbd6c709b0 - - - - -] [7c38fc9d-5a2e-482e-8f51-fd364d05359d] Reconnected to AMQP server on 10.160.77.3:5672 via [amqp] client with port 53712.
  y" E7 j1 ]- q: d( M! G+ e& E* }5 r; t; Z$ k3 r8 B5 @( r/ T$ U
 楼主| 发表于 2021-6-17 15:52:10 | 显示全部楼层
在本人openstack集群环境中,新增一台compute节点,启动nova-compute服务的时候卡死。而已有的计算节点并没有此问题。从侧面反映出整个集群应该是没有问题的,问题出在新增的这台compute节点上。
* i! l# K& @, I9 R$ ?5 ~
& h9 }6 P! F& `1 Y8 O查看/var/log/nova/nova-compute.log日志可以看到报错日志信息:
" o( Y- B6 @3 x8 b& y
4 `4 O& V1 p4 nERROR oslo.messaging._drivers.impl_rabbit [-] [1e21a744-9754-44d3-907b-92e72efdcd7d] AMQP server on controller-150:5672
' H( `5 }! j. r6 n is unreachable: [Errno 104] Connection reset by peer. Trying again in 1 seconds.: error: [Errno 104] Connection reset by peer
' `3 T4 R5 B6 V* ]' W% d! ?3 D% e
ERROR oslo.messaging._drivers.impl_rabbit [-] [1e21a744-9754-44d3-907b-92e72efdcd7d] AMQP server on controller-150:5672
) Q2 j7 z# H8 d* s; g9 z, [" h is unreachable: [Errno 111] ECONNREFUSED. Trying again in 2 seconds.: error: [Errno 111] ECONNREFUSED, D% g" B: ?$ H) ~

0 U6 _5 ~) f, I) oINFO oslo.messaging._drivers.impl_rabbit [-] A recoverable connection/channel error occurred, trying to reconnect: [Err' l! e7 _0 |) K. l4 g7 N
no 104] Connection reset by peer2 I" f2 A% a0 h$ I% B1 f- |/ Q
: F) E/ @/ w+ i! X1 B7 W
ERROR oslo.messaging._drivers.impl_rabbit [-] Connection failed: [Errno 111] ECONNREFUSED (retrying in 2.0 seconds): er
# j5 v, O4 [+ T4 Bror: [Errno 111] ECONNREFUSED! E, G$ ^( X7 ~2 m, {" F: w

6 U, F2 h4 O5 O  r) O: \* hINFO oslo.messaging._drivers.impl_rabbit [-] [1e21a744-9754-44d3-907b-92e72efdcd7d] Reconnected to AMQP server on contr, g+ f( |6 M; b
oller-150:5672 via [amqp] client with port 40872.
% s, e0 j# ^! A: l# O& E1 @
' b  F0 f5 ~- m" q7 F  `+ X) ZWARNING nova.conductor.api [req-9a93ad73-7269-4375-9f67-987d98223d4d - - - - -] Timed out waiting for nova-conductor.  ( z. U: L9 D% ^3 E. l
Is it running? Or did this service start before nova-conductor?  Reattempting establishment of nova-conductor connection...: MessagingTimeout: Timed 6 `/ q5 I, |0 M  f2 E% p+ w
out waiting for a reply to message ID b0de8895bd074645a7d7f6058fc5d8cf7 ?* ~) @. ^- \9 m: t: a( J; f% [3 \

7 S9 P6 S$ n: G2 w" Q0 X 从日志看,是无法连到控制节点的nova-conductor。* v6 o% V+ f2 i7 `! e+ m
  k) S; F3 I; }5 B( h$ h
查看控制节点nova-conductor和rabbitmq的日志,在疯狂刷下面的日志,而43602端口所属进程就是nova-conductor的。说明nova-conductor一直在尝试通过rabbitmq进行通信,但是失败了。
2 X' u5 p0 C. \" c( O& G4 Y" d/ @  z) k' }& E' z; i( q. E5 J3 c
/var/log/nova/nova-conductor.log* B' m* J" \. b! }/ c& G
7 _7 g* Z5 g6 x  H( [& @; p* P
ERROR oslo.messaging._drivers.impl_rabbit [req-602672bc-7325-41ad-ac69-2b735b07c875 - - - - -] [73043348-2b34-44b3-8ab6 r0 j9 l3 s2 i0 }  L
a-7fa9769b64e0] AMQP server on controller-150:5672 is unreachable: [Errno 104] Connection reset by peer. Trying again in 1 seconds.: error: [Errno 101 |0 S. E' V% q0 e- o0 ?4 w
4] Connection reset by peer& F' a! @+ m  S
) ~6 D/ x) E$ |4 S( @
/var/log/rabbitmq/rabbit\@controller-150.log 
, Z9 X' a5 G$ V  b& o( ~9 C* y4 t% |+ B
=ERROR REPORT==== 17-Aug-2020::20:53:24 ===
2 W# F9 V4 e: z8 MChannel error on connection <0.22032.9> (172.5.1.150:43602 -> 172.5.1.150:5672, vhost: '/', user: 'openstack'), channel 1:
* V- c0 r0 A4 _operation basic.publish caused a channel exception not_found: no exchange 'reply_7fab30efd0cf4889a35e402ebf0c18ba' in vhost '/'( |( ?* `8 g. F9 P5 j" |" `) l, K
/ }0 g/ v1 |4 Y4 G
通过查资料,很多人讲:
2 S& g/ g# f7 }7 V3 \( G2 S7 X2 ?* b/ y* D* n! j, d2 |
重启openstack-nova-conductor服务就OK了。 ========然而  并没用。==========
! v3 p4 W$ j( L5 c$ e重新安装rabbitmq-server。 =========然而 并没用。==============& Y0 j0 R/ g* W3 D4 H0 j7 A- M
最后,还是坚信自己一开始的推断,问题出在了新增的compute节点上。
6 o0 u/ x. H7 X. U2 e4 s; z9 N. p! T) j. R, T1 N+ z" D
但是,该节点上的配置文件是来自于模板,与其他计算节点配置一样。。应该排除配置出错的问题。' _1 g( c( {( Z% M

$ B* V1 a- V  d2 @( x3 d) Z( {0 l1 Q既然配置没问题,那有可能出在安装的介质身上了:
" K, [/ Y4 x2 @: v1 S& V7 j- D" p% r4 T( p/ c8 V
已有的集群部署的是openstack queens,新增节点一开始部署的是train版。有问题之后就删了train版,然后重新安装的queens版本。看来是没有删除干净。
" u4 R2 o$ t7 `. U2 i( \9 p4 U1 d' g6 A# \" J- s, v
结论:openstack集群所有节点要严格统一版本,不能使用不同的版本,否则会出现很多莫名其妙的错误。+ m/ M7 \' Z3 u+ K, ^
1 F) Q& a9 t0 r* C' B
解决方案:0 P9 Z2 F* J) R; n& r; y* J

; R" y8 o3 [1 g/ \$ S% i1、通过yum erase package_name 卸载并没有卸载干净。按道理这种方式应该把包依赖一起卸载的。。
8 o+ S; X! b6 A7 }2 J
6 w6 d8 _! A7 a  x& ^2、通过 yum history list  openstack-nova-compute 查看所有和openstack-nova-compute相关的yum安装历史;然后通过 yum history undo ID,将最早安装train版的安装历史回滚掉。这样,就干净的卸载掉了。最后,再重装。问题解决。: X; `/ ^" e' x- C3 b( }# l
 楼主| 发表于 2021-6-17 15:55:06 | 显示全部楼层
使用 rabbitmq 中 heartbeat 功能可能会遇到的问题
$ e& I9 O2 y: U* J# O【问题场景】       客户端以 consumer 身份订阅到 rabbitmq server 上的 queue 上,客户端侧在 AMQP 协议的 Connection.Tune-Ok 信令中,设置 heartbeat 为 0,即要求服务器侧不启用 heartbeat 功能。服务器由于异常断电原因停止服务,结果客户端在短时间内无法感知到服务器端已经异常。; V( b- R' ?1 C  x3 y

! c. p/ O& [: {  B! w: F刚刚出现这个问题时,就有测试人员和业务人员找到我这边说:经过改造的 rabbitmq-c 库可能存在重大 bug,服务器都关闭了,客户端怎么还那像什么都没发生一样继续工作着呢?听到这种疑问,我只问了两个问题就想到了答案:
+ f/ x+ y. k* K# ]+ `4 B
" T# X5 t! {1 D  y  ^. v8 ^! d7 v业务中是不是仅仅作为 consumer 运行的?( p% u1 h7 I1 _& A( W
服务器能否确认是因为异常断电导致停止服务?$ s% \' f, j/ ?! d5 Z7 ]+ ?
服务器和业务程序之间是否还有中间路由设备?
* {, n  R6 m3 x/ \& m, M. I8 M业务人员告诉我上述问题的答案分别是:是的、是的、没有。呵呵~~所以答案就已经确定了,你想到了么?
* w5 O, x. ^! t# N6 Q! i$ k- x2 ^  k9 A% w
【问题分析】
, I5 R* B$ a5 ?; H 这个问题可以从以下两个层面进行分析:
2 Z% k: U# x" K( K3 U+ S  B
0 o! h  D2 E( y, D, o7 MTCP 协议层面8 `" c1 @6 y2 [) @) \5 j- A8 ~/ _& D" q
在此层面上讲,上述问题属于典型的 TCP 协议中的“半打开”问题,典型描述如下:
6 t* N8 l3 y/ _. D7 \9 O 如果一方已经关闭或异常终止连接而另一方却还不知道,我们将这样的 TCP 连接称为半打开(Half-Open)的。任何一端的主机异常都可能导致发生这种情况。只要不打算在半打开连接上传输数据,仍处于连接状态的一方就不会检测另一方已经出现异常。 半打开连接的一个常见原因是,当客户主机突然掉电,而不是正常的结束客户应用程序后再关机。当然这里所谓的客户机并不是仅仅表示客户端。
+ {& S! z% K- l8 k) P 在这种情况发生时,作为 TCP 链路上只接收不发送数据的一方,只能依靠 TCP 协议本身的** keepalive 机制**来检查链路是否处于正常状态。而通常 keepalive 机制下,需要大约 2 个小时时间才能触发。6 d- z' B4 A6 z8 P9 i- O9 O6 m9 i
  f& e/ b# U/ d& H) W
; V0 U$ L8 j) k! D9 `! a
AMQP 协议层面
" \! `3 q  ~; [9 V, G$ b在此层面上讲,客户端由于是作为 consumer 订阅到 queue 上的,所以在该 AMQP/TCP 连接上客户端不会主动发送数据到 rabbitmq server 侧。当服务器由于异常断电停止服务后,consumer 不会接收到 AMQP 协议层面的终止信令,所以无法感知对端的情况。
4 V% }' B& a+ @& F! B: U4 c
4 l! i, i: u+ x一种可能的解决办法是客户端侧在接收 N 次超时后,通过发送 AMQP 协议中的 Heartbeat 信令检测服务器端是否处于正常状态。0 V% p+ ?: r8 I4 @& j) O& q

' y( E  B( }8 W+ X3 ?& ^在场景描述中说道“客户端侧在 AMQP 协议的 Connection.Tune-Ok 信令中,设置 heartbeat 为 0”,如果是将 heartbeat 设置为 30 会如何?答案是会同时触发服务器端和客户端的 heartbeat 功能,即服务器端会在一段时间内没有数据需要发送给客户端的情况下,发送一个心跳包给客户端;或者一段时间内没有收到任何数据,则判定为心跳超时,最终会关闭tcp连接(参考这里)。而客户端侧同样会触发对发送和接收 heartbeat 计时器的维护,分别用于判定发送和接收的超时情况。( @4 P. `# d& Q2 L$ u8 v- R
! G0 j# r3 z7 ^( j# c
所以,需要解决的问题可以描述为: 客户端作为 consumer 订阅到服务器上的 queue 后,在无业务数据需要处理时,需要通过检测 Heartbeat 帧(信令)来判定服务器是否处于异常状态(换句话说,自己是否已经是“半打开”的 TCP 连接)。
1 U9 h& I, U+ ~/ p. r. [- A' q9 K4 F/ d! n
【解决办法】: Q" O9 p3 T! O( U7 g
建议的解决办法如下:
# h* I+ }) v/ Q* d! M- }8 l
- y2 l& X' n$ D+ L: f 客户端必须启用 heartbeat 功能(解决“半打开”问题的基础);
6 `4 k4 Y7 F4 R 客户端需要支持在发送空闲时,发送 heartbeat 的功能(因为目前客户端作为 producer 是长连接到 rabbitmq server 上的);
: W  m9 E+ H- I7 [/ l 客户端需要支持在接收空闲时,通过检测服务器端发送来的 heartbeat 帧来判定服务器端(或网络)是否处于正常状态(因为客户端作为 consumer 也是长连接到 rabbitmq server 上的,同时不会主动向 rabbitmq server 发送数据)。- `- V$ M3 u# N( E3 ^3 l5 O

2 t9 E! N4 X! j- w1 I
+ |" q6 ?( W8 t总结:
, ?) \- o$ Y& l/ C只要客户端启用 heartbeat ,那么服务器就会在满足“一定条件”时,定时向客户端发送 heartbeat 信令,同时也会检测在空闲状态达到规定时间后是否收到 heartbeat 信令;而客户端侧作为 consumer 时,需要判定是否接收到数据(无论是常规数据还是 heartbeat 信令),若在一定时间内没有接收到数据,则认为当前链路可能存在问题。后续可以从业务上触发 consume 关系的重新建立。
3 ^3 p0 s3 ~; T9 x/ P; Q$ r( H8 C. i& |
背景
. j' a% i$ k' I由于长期以来,在我们的 Node.js 服务端项目中,离线任务大部分用的是 kue,这是个轻量级的任务队列,之前 也有过介绍。而周五那天我正准备将之前的 kue 队列重构成 RabbitMQ 的队列的相关代码上线。' J% C! ]' n7 ~6 l) e' D6 v2 l
/ h) }: V4 e  P
RabbitMQ 任务队列是我基于 amqplib 实现的,在生产环境跑了半年有余,没什么大问题。
4 m! o6 P/ g% x8 u2 n% ~' x! N) Z, L: s
但是,按照墨菲定理,你最担心的事情总会发生,或者说:出来混迟早是要还的。! _) z: V+ |/ {( r. T
- ?" S5 b+ f2 _  \( ]# I
悲剧
9 a+ u' ^% I1 R6 T% Z8 u5 g/ t4 w结果,明明在预发布环境测试没问题的,却在正式环境完全不起作用,一直在报 EPIPE 的错误,并且在之后 ack 时报 channel closed 的错误。
# u9 @- G( S8 P: v1 R0 p: Y  a8 }8 p. g4 H' b3 I% D
同时,RabbitMQ 管理后台看到,任务队列在一直堆积,已经累计了 5k 的任务量,可能你会觉得不多,但是如果告诉你,每个任务需要执行 1 到 20 分钟不等呢?
, t% a& \0 w% I& G# W: G! [' r# Y
5 J, U5 M1 E8 }$ }& Y显然,先是把我吓了一跳,不过又马上镇定下来,毕竟处理过的线上事故大于十个手指能数的数量了。
# K$ h) Z$ ~1 W3 K  `! T/ I! e) }5 Z, y
, L9 z$ h% b. o  X; T$ H) [回滚2 T9 ], b6 J' j
冷静想了想,这个离线任务里的业务虽说重要,但一时的任务堆积关系不是很大,而且任务会重新创建,回滚到旧代码就行,于是我将所有的代码一键回滚。7 |$ n" ^% |7 x! j" _3 Q3 c

5 \1 \, a! ?% P  T$ ]现在,改来找问题原因了。% E! @. B! \* {, [2 {

  c- l3 ?1 U5 V- I9 P1 n5 r) U寻找
* S$ L  R: ^- {/ a) @# [按照目前的所掌握的信息,似乎还不能定位问题所在,大致能确定的是:TCP 连接有问题,导致 ack 数据写到了已经关闭的 sockets 上面了,才会导致 EPIPE 的错误。! v: }5 v' {9 U0 P: V

9 G8 i8 @2 z" lTCP 连接为什么会关闭连接?
7 w$ m! H# H, u8 P, a! W0 K一般来说,TCP 正常的关闭,会有四次握手:
. Z1 x# \; S5 Y9 S4 A& ?3 x6 e7 p4 N' u' w6 [2 |7 t/ |" @! H* M0 J2 Z
『我要关了哈』# s! @, ]: V4 @9 w  H; @) w2 P1 E
『好的』,『我也要关了』
3 J5 v8 @1 Y0 c& H; G* \+ D# r3 e 『恩,拜拜』, r8 |5 A- Y5 A5 w- X# @3 |; I
; J8 S/ e, h1 v1 H( i+ j: U
* b6 Y& e( b4 g+ Y* z! ^. g
而不正常的错误,会有 ECONNRESET 或者 Connection reset by peer 之类的错误提示,EPIPE 的话,一般是对方主动关闭,而没有通知到我方。
# O. [0 @% S" n7 W1 h% b' d/ K3 F3 ^/ ^% b& V& N
于是,原因显然是需要在对方机器上去找,因此登录到 RabbitMQ 的机器上查看日志,果然,发现了非常多的错误日志:% r# H3 \9 F/ b% K
+ s+ A% K+ O+ o/ O- y" r
=ERROR REPORT==== 9-Jun-2017::16:07:39 ===
8 J* _& C+ K1 e/ ?4 m closing AMQP connection <0.9305.6670> (X.X.X.1:33647 -> X.X.X.2:5672):
; d: M0 {. \/ D8 _0 H4 w missed heartbeats from client, timeout: 60s
& g7 `% I" ?6 d0 p/ a( H - \6 L0 r, x# B
9 e+ H5 \- A$ Z- M: ^9 f3 p
这是什么意思呢?关键信息是最后一行,missed heartbeats from client, timeout: 60s 。6 e( C8 ]+ W1 `5 s; p* r5 D
0 W: O+ l* G0 J1 ]% V- b
很明显,超过默认 heartbeats timeout 的时间了,于是 RabbitMQ 认为这个客户端已经不行了,所以主动断了连接。# S/ y( W3 C; ?
3 Z- M; \. U# k% Q: g# K% k
好了,那么继续下一步。
  n( e3 ~# Y( z' n% `1 W
2 X0 \+ n( f/ m  y; ]- l为什么会出现 heartbeats timeout ?0 U; v7 ]2 L' o- e( R$ |+ a6 g
在 RabbitMQ 官方文档上 [1] 找到这样的解释:在 server 3.0 以及之后的版本中,client 以及 server 会协商一个 timeout 值,默认是 60s (3.5.5 之前是 580s),回过头来看服务器版本,已经大于 3.5.5,(其实看日志也知道了),也就是 60s。
7 V3 D% q- A( c# q, ]" E' X9 B6 \
9 u. r; I7 n8 D2 Kserver 每隔 timeout / 2 就会发送一个心跳包,如果都错过,就会认为这客户端没救了,会主动关闭连接,然后客户端需要重新连接。8 m, g: P- Q# X& M% Z0 ^* `

4 p6 l! ]5 L5 ]& m, m于是,兴奋地赶紧设置下 heartbeat 时间,来个 3600s。
5 u+ c6 ^0 D1 k0 O5 i2 w$ u. a. I4 d! v* a* {0 a4 `8 u
很明显,问题没那么简单,错误还是在出现。9 Z0 s4 _$ U) i# z5 c
1 [% |3 [* j+ G$ h# {+ V/ t
回过头来,再看看文档,注意 『协商』 这两个字,也就是说,结果不是我设置了就能成功的,server 该怎么做还是怎么做,于是 60s 的默认 timeout 不能通过 client 来修改。  O1 n8 r$ w6 E9 B% i
0 l7 U. M4 i+ i. F9 t2 V, i; l4 r+ s  m
但是这会儿我又不敢修改了,server 的 timeout 是全局的 [2],如果改了就意味着所有的连接都是这个数了,这可太危险了。
8 Y# P3 m' |5 N' |, u+ A
  s% X( ]) S/ d: y8 K# e/ {整理下思路,看看手头上已有的信息,于是把眼光放到了 client。
8 w( p+ C" q& \9 e* P
$ D3 e( ]! w+ B- V为什么会超过默认 heartbeats timeout 的时间?
2 G4 d: g$ s% X- K9 H* s6 e4 d其实这会儿,答案已经呼之欲出了:) b4 E6 x4 T' N
% N" X1 c0 b" W& W0 X7 D
事件循环太长导致5 }5 K" j4 M+ D0 W, ]) ~
) Z. o9 A. f2 a2 @" f7 R
Node.js 不同于其它正常语言,它是单进程模型,没有所谓的进程并发,即使底层的线程也是为了异步 io。8 z2 \9 T4 G8 ^& r

/ D0 N- m  ?6 b% U* s; W也就是说,一旦一个事件里面的 CPU 被占满,其它 io 操作都会在事件队列中等待,导致事件循环过长。而在这个问题中,它的表现就是:client 的心跳包所在的事件,无法通过 TCP 这样的网络 io 操作发送至 server。
1 u' {& p# ?7 Y+ m4 a3 t0 {$ g, p; K5 x  B  |3 X: \; S' [
这才明白,我重构的部分是 CPU 密集型的任务,这恰恰是 Node.js 最软肋的地方。
5 R  ~! S8 s6 j0 _( v! {/ [, Q% D- ]: K: U
解决
9 z0 Z8 e0 S) |显然对于 CPU 密集型任务,我们一般有这几种方案:) D, i) {2 _5 n3 ]

7 v+ n% J2 J( }2 xfork 一个进程去处理,父进程负责 RabbitMQ 通信,子进程负责跑任务;
  K1 w; N- Z9 psetImmediate,分拆 CPU 任务;8 c7 _4 {9 y' }- b
换语言,用 Go,Rust 或者 Python之类的语言去处理;
3 ~/ }6 f' j- u  |那么,为了尽快解决线上的问题,第一个就是我们的选择:最快,最直接。+ T$ {, A# K% J/ G3 z0 u- o" e
2 Q+ y4 I+ C& i2 [* ~
总结
) X9 C; B5 |6 N! x( t# K! J, Lstaging 环境不一致问题需要解决;
7 ^: o* o: ^4 P9 i' O+ v重构有风险,入坑需谨慎;5 o; K' a/ p1 E+ u
造轮子可以,测试需完善;
' y/ g8 e; E) O' u# M$ W* \$ s1 DRef2 o, O* U9 H1 f6 ]
https://www.rabbitmq.com/heartbeats.html% u9 W6 `5 x, H; x
https://www.rabbitmq.com/configure.html  V7 V9 d! S9 N" e$ N/ w
确保与心跳和阻塞连接超时的良好连接
' r7 B1 W3 N/ K* I0 N! o此示例演示了心跳的明确设置和阻止的连接超时。
7 ?" B1 N' J2 w' W' i6 I* i" o1 {' f
从RabbitMQ 3.5.5开始,代理的默认心跳超时从580秒减少到60秒。因此,在同一个运行Pika连接的线程中执行冗长处理的应用程序可能会因心跳超时而出现意外断开的连接。在这里,我们为心跳超时指定显式下限。& L& _0 g9 p8 ~! G  n
$ u; N; O! \: ^" V
当RabbitMQ代理耗尽某些资源(例如内存和磁盘空间)时,它可能会阻止执行资源消耗操作的连接,例如发布消息。一旦连接被阻止,RabbitMQ就会停止从该连接的套接字读取,因此客户端的命令不会通过该连接上的代理,直到代理解除阻塞。被阻止的连接可能持续一段无限期,停止连接并可能导致挂起(例如,在BlockingConnection中),直到连接被解除阻塞。阻塞连接超时旨在中断(即,丢弃)已被阻止超过给定超时值的连接。& U6 W, C  S! o3 U: |: ~& O& c% D

: F$ G% t) g1 I) U8 A配置hertbeat和阻塞连接超时的示例:
1 t0 A# @, X- c! `& U) H9 f8 ~
$ Q# T) u& W& q7 B' aimport pika
' Y# b) v5 t* o7 X; x; V& {& a; l$ j' @7 ~& y# _; w
def main():
5 x. m7 |! [* r0 [# C2 a4 ^: ^  Z/ j( W7 h) k
    # NOTE: These parameters work with all Pika connection types
& {/ n; r( n, I6 ^    params = pika.ConnectionParameters(heartbeat_interval=600,
! d7 _7 k5 S4 v                                       blocked_connection_timeout=300)- L& G+ W+ r, g* h, C0 h

3 y( q! o% O- |( _, s' W! @* f    conn = pika.BlockingConnection(params)+ b2 c: ]# b7 w1 n0 Q6 z1 w: S: ]
& @% o* e, R& b% ], a& w
    chan = conn.channel()
0 {* ?, E7 U# W; ~6 M) z; b* d" v' ~; _  h! t, Q
    chan.basic_publish('', 'my-alphabet-queue', "abc")
+ r6 l8 W# D; ~; N& V) @% G3 a( _$ F4 D. q/ `
    # If publish causes the connection to become blocked, then this conn.close()6 C1 w$ M/ w, @" T' ]
    # would hang until the connection is unblocked, if ever. However, the
; n& G+ @' @. z" W/ t; D7 f    # blocked_connection_timeout connection parameter would interrupt the wait,; b9 z9 ~4 y9 Y- |/ I
    # resulting in ConnectionClosed exception from BlockingConnection (or the
2 |' z  s! p' j9 Q    # on_connection_closed callback call in an asynchronous adapter)
( j6 D/ e( q+ I    conn.close()1 z1 }  ]! w' _5 N9 ]3 T' J
% c. ]' e* }3 w& e8 M! Z
if __name__ == '__main__':
: `7 F) m6 O2 }$ X    main()
 楼主| 发表于 2021-6-17 15:55:36 | 显示全部楼层
rabbitmq 的心跳机制&应用
5 }% n7 E/ T/ h& R 官方文档说:( ?5 x( _  e9 Q6 `0 u& Y
1 C) ]6 K, B. W( S( _
If a consumer dies (its channel is closed, connection is closed, or TCP connection is lost) without sending an ack, RabbitMQ will understand that a message wasn't processed fully and will re-queue it
! T. X! {1 m( {6 f& }! {, r0 @
) G/ R: \- c8 ~/ X即: 如果消费者进程挂掉了(channel关闭, connection关闭,或者tcp连接丢失), 没有发回确认信息, RMQ将认为消息没有被处理完, 将重新排队等待分配。0 t  x7 y) E* A) {0 R& F. u8 p
  ]) y7 e" t4 \& W: `
1 D3 Q# s5 S$ i, n" h# c, c
, K  z0 a) z& @
but how?
8 z% ^# o3 ?; ?6 _; I
" M- i2 K; b4 w/ _; \" s: H答案是:通过心跳来监控。
9 T, p4 @/ {! m9 U1 `- ]( @- ?! J" o7 Q' m7 O" y8 B, S- w

+ O& E1 ?+ l! Z
% |: ?/ g' {2 g! S" ^* O5 J官方文档在这里:https://www.rabbitmq.com/heartbeats.html2 B' f9 s' e+ z

, d5 q6 @4 ?6 L6 z3 `6 c- t摘要如下:
; q) G+ n1 v0 Y- t  D9 e" Y/ W% R# F3 b9 |$ \) D8 ~% A
=====================================================================
! Y( a+ M! m( Y% h' x1 t; t# |- D: k5 s1 g9 Z7 u0 T1 U" H$ K
Detecting Dead TCP Connections with Heartbeats/ q0 S3 l5 C% t" d7 C
用心跳监控tcp连接是否丢失" Z; O) G* F! j  h" b
Introduction5 p) ^1 x) ^: q
介绍
0 F* z6 C9 z0 yNetwork can fail in many ways, sometimes pretty subtle (e.g. high ratio packet loss). Disrupted TCP connections take a moderately long time (about 11 minutes with default configuration on Linux, for example) to be detected by the operating system. AMQP 0-9-1 offers a heartbeat feature to ensure that the application layer promptly finds out about disrupted connections (and also completely unresponsive peers). Heartbeats also defend against certain network equipment which may terminate "idle" TCP connections.* l+ `; U, D/ K4 \2 |
: o9 d! D1 L' k# t! b9 O
网络故障很多种,有时很微妙(比如,丢包比率和高)。 分布式的tcp连接采取适中的时间(比如Linux默认配置大约11分钟),方便操作系统检测。AMQP 0-9-1提供heartbeat(心跳)特性来确保应用服务层及时发现已崩溃的连接(和完全无相应的peers)。 心跳机制也能保证进程不被某些网络设备给杀掉。, E0 y  @7 ^4 S4 N) g6 o/ Y
, P& I8 a! f. F) E+ l9 e9 C
Heartbeat Timeout Interval
9 X! D! b: u" \- k2 K心跳超时间隔
2 {7 d- V' v: e5 mThe heartbeat timeout value defines after what period of time the peer TCP connection should be considered dead by RabbitMQ and client libraries. This value is negotiated between the client and RabbitMQ server at the time of connection. The client must be configured to request heartbeats. In RabbitMQ versions 3.0 and higher, the broker will attempt to negotiate heartbeats by default (although the client can still veto them). The timeout is in seconds, and default value is 60 (580 prior to release 3.5.5).
: Y( k& P8 H8 @6 v- s4 V9 @/ M2 Q4 d( h
心跳超时值决定了tcp相互连接的最大时间, 超过了这个时间, 该连接即被RMQ和客户端视为丢失(dead)。 这个值在客户端和服务器建立连接的时候协商确定。客户端需配才能发心跳包。 RMQ3.0及以上版本, RMQ将试着将beatheart协调为默认值(客户端可以否决这个值)。 超时时间单位为秒,默认值为60( 3.5.5发布版之前是580)。! p( ], O: o% f+ b3 i: x
; K( u" ]! t& n( `
Heartbeat frames are sent about every timeout / 2 seconds. After two missed heartbeats, the peer is considered to be unreachable. Different clients manifest this differently but the TCP connection will be closed. When a client detects that RabbitMQ node is unreachable due to a heartbeat, it needs to re-connect.% ?, d2 ^) Y+ G8 `% L
; k( t$ [! u$ }$ c
心跳包每半个超时时间发送一次。 丢失了两个心跳包, 连接被认为不可抵达。 不同的客户端有不同的提示, 但tcp连接都会被关闭。 当客户端检测到RMQ节点不可抵达(根据心跳判定), 它需要重新连接(到服务器)。
2 B7 H. Q0 x3 ~$ w' C. |7 N1 X9 ]$ K0 A7 I# a- s. v- ~6 L
Heartbeats can be disabled by setting the timeout interval to 0.
4 ?' h: A, v. ]+ s1 F7 C0 Y3 }7 f0 g1 R6 `! m; E
心跳机制可以被禁用:设定超时间隔为0。" `! _  U: B( V: q9 v  X4 l
( d& L8 {7 D- I  D  F8 ]
您需要登录后才可以回帖 登录 | 开始注册

本版积分规则

关闭

站长推荐上一条 /4 下一条

北京云银创陇科技有限公司以云计算运维,代码开发

QQ|返回首页|Archiver|小黑屋|易陆发现技术论坛 点击这里给我发消息

GMT+8, 2026-4-8 16:59 , Processed in 0.042760 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

© 2012-2025 Discuz! Team.

快速回复 返回顶部 返回列表