内容提要
本文讨论了长连接黑洞问题及其对高可用切换的影响。长连接在网络故障时可能导致业务长时间无法恢复,主要由于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可能随时被杀掉,导致客户端无法及时感知服务不可用,从而出现长连接黑洞问题。