解决 RabbitMQ 集群 Channel shutdown: connection error 错误(HAProxy 负载均衡)
具体错误信息:
2018-05-04 11:21:48.116 ERROR 60848 --- [.168.0.202:8001] o.s.a.r.c.CachingConnectionFactory : Channel shutdown: connection error
2018-05-04 11:21:48.116 ERROR 60848 --- [.168.0.202:8001] o.s.a.r.c.CachingConnectionFactory : Channel shutdown: connection error
2018-05-04 11:21:48.125 INFO 60848 --- [nge.consumer1-8] o.s.a.r.l.SimpleMessageListenerContainer : Restarting Consumer@5196e177: tags=[{amq.ctag-d_wIlZIGxM3f0fsxkmYQfA=my_test_exchange.consumer1}], channel=Cached Rabbit Channel: AMQChannel(amqp://admin@192.168.0.202:8001/,1), conn: Proxy@25a73de1 Shared Rabbit Connection: SimpleConnection@25fca927 [delegate=amqp://admin@192.168.0.202:8001/, localPort= 56258], acknowledgeMode=AUTO local queue size=0
2018-05-04 11:21:48.126 INFO 60848 --- [nge.consumer1-9] o.s.a.r.c.CachingConnectionFactory : Attempting to connect to: [manager1:8001]
2018-05-04 11:21:48.393 INFO 60848 --- [nge.consumer1-9] o.s.a.r.c.CachingConnectionFactory : Created new connection: rabbitConnectionFactory#2b8bd14b:12/SimpleConnection@3fb9795a [delegate=amqp://admin@192.168.0.202:8001/, localPort= 56260]
2018-05-04 11:21:49.059 INFO 60848 --- [nge.consumer1-8] o.s.a.r.l.SimpleMessageListenerContainer : Restarting Consumer@58b42519: tags=[{amq.ctag-T1HyrOd5Ykr_VQZDwxRslA=stream_exchange.consumer1}], channel=Cached Rabbit Channel: AMQChannel(amqp://admin@192.168.0.202:8001/,2), conn: Proxy@25a73de1 Shared Rabbit Connection: SimpleConnection@3fb9795a [delegate=amqp://admin@192.168.0.202:8001/, localPort= 56260], acknowledgeMode=AUTO local queue size=0
Spring Boot 配置 RabbitMQ(使用 HAProxy 负载均衡):
spring:
application:
name: stream-rabbitmq-producer
rabbitmq:
host: manager1
port: 8001
username: admin
password: admin123456
最近使用 RabbitMQ 集群的时候(HAProxy 负载均衡),频繁的出现上面错误信息,但是消息可以正常被消费掉,如果只使用单机版 RabbitMQ 的话(不使用 HAProxy),是没有任何错误的。
被这个问题困扰了很久,Google 找了很多资料,也没有找到解决方案,无意间找到一篇文章:RabbitMQ and HAProxy: a timeout issue
文章说,如果使用 HAProxy 配置 RabbitMQ 高可用集群的话,则会遇到客户端连接超时问题。
为什么会出现此问题呢?因为 HAProxy 配置了客户端连接超时参数(timeout client ms
),如果客户端连接超过配置的此参数,那么 HAProxy 将会删除这个客户端连接。
RabbitMQ 客户端使用永久连接到代理,从不超时,那为什么还会出现问题?因为如果 RabbitMQ 在一段时间内处于非活动状态,那么 HAProxy 将自动关闭连接(有点坑呀?)。
那如何解决这个问题呢?我们看到 HAProxy 提供了一个clitcpka
参数配置,它可以从客户端发送TCP keepalive
数据包。
我们就使用它,但发现配置了之后,还是出现了上面的问题。
为什么呢?
[…]the exact behaviour of tcp keep-alive is determined by the underlying OS/Kernel configuration[…]
什么意思?意思就是TCP keepalive
数据包的发送,取决于操作系统/内核配置。
我们可以使用命令查看(HAProxy 所在服务器中的tcp_keepalive_time
配置):
[root@manager1 ~]# cat /proc/sys/net/ipv4/tcp_keepalive_time
7200
tcp_keepalive_time
默认配置时间 2 个小时,表示发送TCP keepalive
数据包的间隔时间是 2 个小时,或者说每隔 2 个小时发送TCP keepalive
数据包。
这么说就清楚了吧,虽然我们在 HAProxy 中,配置了clitcpka
参数,但因为系统发送TCP keepalive
数据包的间隔时间过长,远远超过 HAProxy 中的 timeout client
超时时间(默认好像是 2 秒),所以客户端连接每隔 2 秒,就被 HAProxy 无情的给删除掉,然后不断的被重建。
说了那么多,我们该怎么解决此问题呢?
两种方案:
- 修改系统的
tcp_keepalive_time
配置,间隔时间低于 HAProxy 配置的timeout client
超时时间(因为有可能影响其他系统服务,不推荐)。 - 修改 HAProxy 中的
timeout client
超时时间,配置大于系统的tcp_keepalive_time
间隔时间(推荐)
因为系统tcp_keepalive_time
发送TCP keepalive
数据包间隔时间是 2 个小时,所以,我们将 HAProxy 中的timeout client
超时时间,设置为 3 个小时:
timeout client 3h
timeout server 3h
完整示例配置:
[root@manager1 ~]# cat /etc/haproxy/haproxy.cfg
global
log 127.0.0.1 local0 info
global
log 127.0.0.1 local1 notice
daemon
global
maxconn 4096
defaults
log global
mode tcp
option tcplog
option dontlognull
retries 3
option abortonclose
maxconn 4096
timeout connect 5000ms
timeout client 3000ms
global
timeout server 3000ms
balance roundrobin
listen private_monitoring
bind 0.0.0.0:8000
mode http
option httplog
stats refresh 5s
stats uri /stats
stats realm Haproxy
stats auth admin:admin
listen rabbitmq_admin
bind 0.0.0.0:8002
server manager1 manager1:15672
server manager2 manager2:15672
server manager3 manager3:15672
listen rabbitmq_cluster
bind 0.0.0.0:8001
mode tcp
option tcplog
balance roundrobin
timeout client 3h
timeout server 3h
server manager1 manager1:5672 check inter 5000 rise 2 fall 3
server manager2 manager2:5672 check inter 5000 rise 2 fall 3
server manager3 manager3:5672 check inter 5000 rise 2 fall 3
重新运行 HAProxy,然后 RabbitMQ 测试成功:
相关文章
- JetBrains Rider for mac(跨平台.NET IDE集成开发) v2022.3.1激活版
- 交互周期表:网络中心度(Network Centrality)
- ECCV2022 | PCLossNet:不进行匹配的点云重建网络
- Redis
- SQLSERVER 的复合索引和包含索引到底有啥区别?
- SQLSERVER 的主键索引真的是物理有序吗?
- SQLSERVER 居然也能调 C# 代码 ?
- 再聊一下那 SQLSERVER 行不能跨页的事
- 聊一聊 SQLSERVER 的行不能跨页
- 一次SQL调优 聊一聊 SQLSERVER 数据页
- 记一次 .NET 某安全生产信息系统 CPU爆高分析
- 记一次 .NET 某工控MES程序 崩溃分析
- 玩好.NET高级调试,你也要会写点汇编
- 记一次 .NET 某工控软件 内存泄露分析
- 记一次 .NET 某电子厂OA系统 非托管内存泄露分析
- 聊一聊如何截获 C# 程序产生的日志
- .NET 7 的 AOT 到底能不能扛反编译?
- 记一次 .NET 某自动化采集软件 崩溃分析
- 从 WinDbg 角度理解 .NET7 的AOT玩法
- 记一次.NET某工控图片上传CPU爆高分析