腾讯云负载均衡connect reset by peer的问题
背景:
基于zuul2开发的网关项目在阿里云上试运行3个月后开始在腾讯云部署,在单机测试过程中没发现任何问题,但是部署网关的实例挂在LB下每次客户端请求都会在网关层打印connect reset by peer的错误,可是客户端并没有任何感知,所以可以确定是腾讯云的lb到lb后面的机器这一段报文出了问题,具体原因是什么?为什么客户端没有感知?请见我后面一步步分析。
知识准备:
TCP标识:
SYN(建立联机) ACK(确认) PSH(传送) FIN(结束) RST(重置) URG(紧急),一般能了解前四种就够用了,后两种是异常处理。
三次握手:
第一次握手
客户端向服务器发出连接请求报文SYN,这是三次握手中的开始,表示客户端想要和服务端建立连接。
第二次握手
TCP服务器收到请求报文后,如果同意连接,则发出确认报文ACK,同时询问客户端是否准备好SYN。
第三次握手
TCP客户进程收到确认后,还要向服务器给出确认ACK,客户端表示我已经准备好。
四次挥手:
第一次挥手
TCP发送一个FIN(结束),用来关闭客户到服务端的连接,这个FIN可以由客户端发起,也可以由服务端发起,为了方便解释说明,此处拿客户端发起来举例。
第二次挥手
服务端收到这个FIN,他发回一个ACK(确认),服务端就进入了CLOSE-WAIT(关闭等待)状态,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。
第三次挥手
服务端发送一个FIN(结束)到客户端,服务端关闭客户端的连接,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
第四次挥手
客户端发送ACK(确认)报文确认,关闭完成。
Http的connection头
http的connection有close和keep-alive两种,网上有大量介绍两者区别的资料,我这里就不再搬砖了。简单理解就是前者是服务端发完数据就直接关闭,后者是发完数据后必须要等着主动来关闭,结合前面的知识点就是挥手的时机不同。
connect reset by peer:
这个异常产生的原因就是一端异常导致另一端的重连,两个方向(服务器到客户端,客户端到服务器)都有可能。例如服务端还没传送完返回信息客户端就已经关闭连接了,服务端就会报这个错误。
错误分析:
有了这么多知识储备后回到本次案例,调用链路是客户端先到lb再到lb后的服务器,因为从表象来看客户端对这个异常没有任何感知,是成功完成了通信的,所以可以排除握手和服务器内容返回这部分有问题,基本锁定是服务端把数据传送完毕后的阶段,那就只剩下四次挥手这一块了。要彻底排查这种网络上的异常,只能抓包看下。
先看下正常的包,没有经过lb,客户直接请求到服务器:
可以清楚的看到握手、传递信息、挥手搞别的过程。
再看下经过lb的包:
明显没有看到四次挥手,而且注意看最后两行,lb给后端服务发送ack=397后31微秒后就认为后端没有收到直接发送了RST重试,这很不科学。第一:31微妙时间太短,网络上一来一回还是需要点时间的;第二:TCP协议里有套接字RTO(Retransmission TimeOut)规定了超时时长,我从报文中也可以看到这个时长,大好几个数量级呢。所以基本可以肯定lb没有认真遵循tcp协议要求。
我后来还尝试过客户端请求时强制把connection配置为close,可抓到的包仍然是keep-alive,可以确定是lb强制用keep-alive方式对后端服务器做的请求。
而阿里云的设计却恰恰相反,lb强制用close方式对后端做请求,以下是阿里云抓包情况:
总结:
腾讯云的负载均衡在设计上应该是追求快速释放,收完服务器的信息简单暴力关闭了,并没有严格遵循挥手协议,所以对客户端没有任何影响,对于服务端就不够友好了。
还没有评论,来说两句吧...