kavin

负载均衡故障缉凶:一个MSS值引发的疑案

kavin 运维技术 2022-11-12 488浏览 0

负载均衡设备位于客户端和真实服务器之间,一旦访问发生问题,在客户经过简单诊断后,负载均衡设备往往会成为首要被怀疑的对象。客户一般这样质疑:为什么我直接访问服务器没有问题,通过你的设备访问就不行了呢? 质疑的确实有道理,但大多数事情往往不是非一即二这样简单,有很多东西都在互相影响,这就使得真相迷雾重重。

某一天接到某客户报障,说是通过负载均衡设备访问某一业务的时候,页面无法打开或者等半天后只打开了部分页面,而客户端如果直接访问服务器,则可以顺利打开页面。

事情很明显,这中间肯定是有问题存在。登录负载均衡设备检查配置和log,并取一些内部诊断信息,没发现什么错误,只剩下唯一的办法:去客户现场抓包分析。

于是开始抓包,同时抓回了出现问题的服务的数据包和其他没有出现问题的服务的数据包。

经过分析,果然有所不同,下面是有问题的抓包内容(抓包1):

负载均衡故障缉凶:一个MSS值引发的疑案

10.52.127.108为客户端地址

10.0.1.112为VIP

10.0.1.99为真实服务器地址

由于是以旁路方式部署,需要转换源IP, 10.0.1.123为经过负载均衡设备转换的客户端地址(snat地址)

负载均衡的VIP配置为HTTP模式,这表示负载均衡设备是以proxy的方式来处理连接,也就是对每个连接,客户端先跟负载均衡设备完成一个三次握手,然后负载均衡设备再跟真实服务器完成一个三次握手。

访问流程:

1) 10.52.127.108访问10.0.1.112

2) 负载均衡设备与客户端完成三次握手

3)然后负载均衡设备把源IP: 10.52.127.108转换成10.0.1.123向服务器10.0.1.99发起连接

4)服务器10.0.1.99与负载均衡设备完成三次握手。

下图是访问没有问题的服务的抓包内容(抓包2):

负载均衡故障缉凶:一个MSS值引发的疑案

10.0.76.2为客户端地址

10.0.1.113为VIP

10.0.1.104为真实服务器地址

由于是以旁路方式部署,同样需要把客户端源IP转换为 10.0.1.123

访问流程跟抓包1相同。

仔细比较两个抓包内容,终于发现了差异出现在MSS值的协商上。

首先我们描述一下Client访问Server过程中MSS值的协行过程:

1) 客户端在向服务器发出SYN包的时候,会带上客户端设备可以接受的最大MSS值,意思是服务器发送到客户端的每个包的内容大小都不能大于这个值。

2) 服务器向客户端回复SYN,ACK包的时候,会比较客户端发来的MSS值和自己设定的MSS值,取两者的最小值作为自己可以接受的最大MSS值返回给客户端,意思是告诉客户端发送到服务器的每个包的内容大小都不能大于这个值。

3) 在实际的传输中,双方往往会取二者中的最小值作为双方互相发送的包大小的最大值。

基于以上通信流程我们来分析一下以上的两个抓包内容:

抓包1:

客户端发出SYN包,标明自己可接受的最大MSS值为1460,负载均衡设备回应自己可接受的MSS值为1400,协商成功后,双方交互的包大小不会大于1400。

负载均衡设备向服务器发出自己的可接受MSS值为1380,服务器回应自己可接受的MSS值120,协商成功后,负载均衡设备发给服务器的包就不能大于120了。

问题正是出在最后跟服务器协商出的大小为120的MSS值上。

我们看到客户端向负载均衡设备发出的第一个请求包大小为905字节,这个包大小不大于1400,所以负载均衡设备接收到了,接着负载均衡设备要把该请求发给选定的服务器10.0.1.99,由于服务器可接收的包不能大于120,所以负载均衡设备只能把客户端发来的请求包分成八个小包发送给服务器,然后一些不可控制的问题就出现了,客户端发出请求包后,需要等待应答,但由于负载均衡设备把一个包分解成8个包后,使得负载均衡设备跟服务器之间的交互时间变长,这个过程中客户端可能会超时重发请求包,而负载均衡设备跟服务器之间那八个小包的处理还可能出现丢包,重传,重装等问题。最关键是客户端在该连接的所有请求发完后如果是发送一个RST包来关闭连接,那么即使该连接上还有内容没传输完,该条连接也会关闭,由于一个请求包分成太多的小包传输,一旦发生客户端发出RST包的这种情况,基本上都会导致数据不能传输完毕,以上种种原因导致了页面不能打开或者不能完全打开的现象。

我们再分析抓包2:

客户端发出SYN包,标明自己可接受的最大MSS值为1460,负载均衡设备回应自己可接受的MSS值为1400,协商成功后,双方交互的包大小不会大于1400。这一点跟抓包1相同。

负载均衡设备向服务器发出自己的可接受最大MSS值为1380,服务器回应自己可接受的MSS值1380,协商成功后,所以双方会以1380的MSS值互相通信。

无论是客户端跟负载均衡设备还是负载均衡设备跟服务器之间,都是一个请求一个应答就能完成交互,不会发生要把包分割的现象,所以不会出现抓包1所出现的问题。

网络通信中由于MTU的设置不当引发的问题屡见不鲜,比如在存在ADSL设备的情况下,如果把设备的MTU设置成1500, 往往客户端的访问会出现问题,这是因为ADSL的PPPoE协议在MTU中占去8个字节,也就是ADSL的MTU最大值最多为1492, 如果客户端跟服务器设的很大,传输的数据包恰好大于1492字节,将导致数据包不能通过。 在程序设计中,程序所取MSS值往往是本机的MTU-40(TCP和IP头各占20个字节,MTU一般设成1500), 所以基本上所有设备所能接受的最大MSS值不可能会大于1500-40=1460, 那么再考虑到网络中可能会存在PPPoE,VPN等设备会占用更多MTU字节,所以各家网络设备厂商提供的网络设备会进一步减小MSS值的设置,一般网络设备设定的MSS值大小为1400左右。

显然1400字节左右的MSS值是网络通信中的正常值,所以服务器返回一个120字节的MSS值这是一个不正常的现象,所以问题的根源在于服务器返回的MSS值不合适,那么这个值是谁返回的呢? 是服务器,也就是说该返回哪个值主动权在于服务器,所以我们诊断问题原因出在服务器上。

接下来的处理需要去检查服务器为什么返回这个值,跟负载均衡设备无关了。但仍然有追踪的价值,因为服务器并不是一直返回120这个值,而是有些时候会协商成1380,这时候访问是正常的,有些时候是返回120,这时候就自然访问不正常。

客户的服务器装的是HP操作系统,应用软件是Oracle的ebs,在我们把问题定位到了服务器后,客户也找了HP的工程师来检查和分析,但无法找出原因。

个人分析问题原因可能出现在如下几个方面:

1) HP操作系统或者网卡驱动程序关于MTU的定义存在可变值,或者

2) Oracle ebs的底层通信程序在MSS值的协商时,会根据一些条件改变MSS值

以上仅仅是猜测,因为没有以上两个厂家的资深工程师的深度参与,无法最终定位结果,所以该问题成为了一个疑案。

继续浏览有关 网络 的文章
发表评论