现象
1 | 025-11-07 13:58:40.051 ERROR [celina-data-center,,] 34880 --- [isson-netty-1-6] o.redisson.client.handler.CommandsQueue : Exception occured. Channel: [id: 0xdd6f0878, L:/192.168.10.182:60652 - R:dmz-zjj.lanniuh.com/172.16.16.33:7073] |
日志中出现的 java.io.IOException: 远程主机强迫关闭了一个现有的连接 错误,通常意味着 Redisson 客户端与 Redis 服务器之间的网络连接被远程端(Redis 服务器或中间网络设备)主动关闭。以下是具体原因分析和解决方法:
一、核心原因分析
该错误的本质是:Redisson 客户端与 Redis 服务器的 TCP 连接被强行终止(非正常断开),可能的触发点包括:
- Redis 服务器主动关闭连接:
- Redis 配置了
timeout参数(默认 0,即永不超时),若设置了非零值(如 300 秒),当连接空闲时间超过该值时,服务器会主动关闭连接。 - Redis 服务器内存不足、重启、宕机或被杀死进程,导致连接中断。
- Redis 配置了
- 中间网络设备干预:
- 防火墙、负载均衡器(如 Nginx、F5)或网关配置了连接超时策略,当连接空闲时间超过阈值(如 60 秒),会主动切断连接。
- 网络波动、丢包严重,导致 TCP 连接被底层协议判定为无效而关闭。
- Redisson 客户端配置不当:
- 客户端未配置心跳检测,无法维持长连接,被服务器或网络设备判定为 “死连接” 而关闭。
- 客户端与服务器之间的
keepalive机制未启用,TCP 层无法检测连接有效性。
二、解决方法(按优先级排序)
1. 检查并调整 Redis 服务器的超时配置
登录 Redis 服务器,执行以下命令查看
timeout配置:bash
1
redis-cli config get timeout
若
timeout不为 0(如300秒),建议临时改为0(关闭超时),观察是否还会出现连接关闭:bash
1
redis-cli config set timeout 0
若需长期生效,修改 Redis 配置文件(
redis.conf):conf
1
timeout 0 # 禁用连接超时(默认值)
注意:
timeout 0表示 Redis 不会主动关闭空闲连接,适合长连接场景(如 Redisson 客户端)。
2. 排查中间网络设备的超时策略
- 联系运维团队,检查防火墙、负载均衡器、网关的配置:
- 例如,Nginx 反向代理 Redis 时,若配置了
proxy_timeout 60s,会导致 60 秒空闲后断开连接,需延长该值(如3600s)或禁用。 - 云服务器的安全组、网络 ACL 可能有类似的 “连接超时” 限制,需调整为适合业务的时长(建议至少 300 秒以上)。
- 例如,Nginx 反向代理 Redis 时,若配置了
- 若无法修改网络设备配置,可通过客户端主动发送心跳维持连接(见步骤 3)。
3. 配置 Redisson 客户端的心跳与重连机制
Redisson 提供了连接检测和自动重连功能,需在客户端配置中启用:
java
运行
1 | // Redisson 配置示例(Spring Boot 可在 application.yml 中配置) |
- 关键参数说明:
pingConnectionInterval:定期发送 PING 命令(如 30 秒一次),确保连接被服务器和网络设备视为 “活跃”,避免被超时关闭。idleConnectionTimeout:客户端主动关闭空闲超过该时间的连接,需小于网络设备的超时时间(如网络超时 60 秒,则设为 50 秒)。
4. 启用 TCP 层的 keepalive 机制
通过操作系统配置 TCP 保活机制,底层检测并维持连接:
Linux 服务器(客户端所在机器):
bash
1
2
3
4
5
6
7
8
9
10
11# 临时生效
echo 1 > /proc/sys/net/ipv4/tcp_keepalive_time # 连接空闲多久后发送第一个保活包(秒,默认 7200)
echo 5 > /proc/sys/net/ipv4/tcp_keepalive_intvl # 保活包重发间隔(秒,默认 75)
echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes # 未收到响应时,重试发送保活包的次数(默认 9)
# 长期生效(修改 /etc/sysctl.conf)
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 10
net.ipv4.tcp_keepalive_probes = 3
# 生效配置
sysctl -p建议将
tcp_keepalive_time设为 600 秒(10 分钟),确保在网络超时前触发保活检测。
5. 检查 Redis 服务器稳定性
查看 Redis 服务器日志(通常在
redis.conf中配置的logfile路径),确认是否有内存溢出(OOM)、崩溃重启等记录。监控 Redis 服务器的资源使用:
bash
1
2
3
4# 查看内存使用
redis-cli info memory | grep used_memory_human
# 查看连接数
redis-cli info clients | grep connected_clients若服务器频繁重启或内存不足,需扩容资源或优化 Redis 内存配置(如
maxmemory-policy)。
三、临时排查手段
抓包分析:在客户端机器使用
tcpdump抓取与 Redis 服务器的通信包,确认连接关闭的发起方(客户端 / 服务器 / 中间设备):bash
1
tcpdump -i any host 172.16.16.33 and port 7073 -w redis_packet.pcap
通过 Wireshark 分析
pcap文件,若看到FIN或RST包来自服务器 IP,则说明服务器主动关闭。测试连接稳定性:使用
telnet或nc模拟长连接,观察是否会被断开:bash
1
2telnet 172.16.16.33 7073
# 保持连接,观察是否会自动断开若一段时间后断开,说明网络层或服务器有超时策略。
总结
该错误的核心解决思路是:通过心跳机制维持连接活跃性 + 调整服务器 / 网络的超时配置 + 启用自动重连。优先检查 Redis 的 timeout 配置和网络设备的超时策略,再通过 Redisson 的 pingConnectionInterval 发送心跳,基本可解决大部分 “远程主机关闭连接” 问题。