长连接黑洞重现和分析

长连接黑洞重现和分析

💡 原文中文,约13800字,阅读约需33分钟。
📝

内容提要

本文讨论了长连接黑洞问题及其对高可用切换的影响。长连接在网络故障时可能导致业务长时间无法恢复,主要由于TCP重传机制。通过调整TCP参数(如tcp_retries2)和设置SocketTimeout及TCP_USER_TIMEOUT,可以显著提高故障恢复效率。

🔎

延伸解读

长连接黑洞的根源与影响

长连接黑洞源于TCP重传机制:当服务端突然消失(如宕机、断网),客户端发送的数据包收不到ACK,会按tcp_retries2参数重传,默认15次约924秒。这导致业务在故障后长时间无法恢复,即使高可用切换已完成。问题普遍存在于所有TCP长连接中,与LVS、K8s Service等无关,但后者可能加剧现象。

业务层应对:超时设置与连接池

业务方必须设置合理的SocketTimeout和ConnectTimeout,避免请求无限挂起。例如JDBC URL中配置SocketTimeout,连接池如Jedis超时后会销毁旧连接,重建时连到新节点。注意Druid连接池在1.2.22版本前有bug,建议将SocketTimeout直接写入JDBC URL。分析类请求可适当调大超时值。

OS与基础设施层优化

OS层面可调整tcp_retries2为5-10次,缩短重传超时;设置TCP_USER_TIMEOUT(需应用支持)可在未收ACK时及时释放连接。对于云上SLB/ALB,配置connection_drain_timeout,在摘除节点后主动发RST,让客户端快速重建连接。keepalive时间建议从7200秒改为20秒,避免闲置连接被LVS重置。

最佳实践与注意事项

最佳实践包括:业务设置SocketTimeout;OS调整tcp_retries2;云负载均衡配置connection_drain_timeout。注意TCP_USER_TIMEOUT更精确但JDK不支持,Netty等框架可绕过。极端情况下,若网络不通,服务端无法发RST,只能靠客户端超时兜底。避免依赖重启业务恢复,应提前在业务和OS层做好超时控制。

❓

Q&A

长连接黑洞问题是什么?

长连接黑洞问题是指在网络故障时,长连接可能导致业务长时间无法恢复,主要由于TCP重传机制造成的。

如何通过调整TCP参数来改善长连接黑洞问题?

可以通过调整tcp_retries2参数、设置SocketTimeout和TCP_USER_TIMEOUT来提高故障恢复效率。

tcp_retries2参数的默认值是多少?

tcp_retries2的默认值为15,这意味着在故障时可能需要900秒以上才能恢复。

设置SocketTimeout有什么好处?

设置SocketTimeout可以控制请求超时时间,避免请求长时间挂起,从而提高业务的恢复速度。

如何在Linux中设置TCP_USER_TIMEOUT?

可以使用setsockopt函数设置TCP_USER_TIMEOUT,指定在未收到ACK时多长时间后释放连接。

长连接黑洞问题在K8S环境中更明显的原因是什么?

在K8S环境中,服务不可靠,POD可能随时被杀掉,导致客户端无法及时感知服务不可用,从而出现长连接黑洞问题。

🏷️

标签

➡️

继续阅读