排查完500异常的原因后,还被下面问题困扰着
1 确定了RST导致500,是否还有其他场景导致500异常。为什么会出现发送了一半的包,接着就把连接给关闭掉的情况?
2 如何模拟这种错误的请求?
3 该问题是一个通用的问题, nginx等负载均衡设备对于这种场景是如何处理的?
5.1 500错误场景分析
继续进行抓包,多分析一些场景
1:连接空闲关闭
客户端先发送了http的一段segment,接着一直不再发送剩下的segment。 服务端连接空闲超时后,就会关闭该连接,导致500异常。
2:FIN关闭
客户端先发送了http的一段segment,接着过了1s后,客户端发送FIN,进行连接的关闭。通过该抓包流程,可以看出服务端收到segment后,返回的ACK,客户端并没有收到。服务端回复ack的信息,客户端一直收不到,导致客户端发送了关闭连接的请求。
通过抓包的分析,产生500请求主要有如下场景
1 客户端发送一段segment,然后发送FIN(关闭连接)
2 客户端发送一段segment,然后发送RST(强制关闭连接)
3 客户端发送一段segment, 服务端超时,进行关闭连接
5.2 请求模拟
该请求就是发送一半http协议数据到服务端,然后再关闭连接。 刚开始一直定位于通过http客户端来做,由于没法在应用层来控制只发送一半的包,导致一直无法实现模拟请求。
尝试直接通过tcp的客户端来做,通过发送一段不完成的http协议数据,然后再关闭连接。选择了jmeter来模拟这种场景。
构造上述的请求,先点击发送,这个时候连接会被hold主,接着点击stop按钮,便能模拟该请求。 如果SO_LINGER设置为0,则关闭发送的是RST包,如果不是0,则关闭发送的为FIN包。
5.3 nginx排查
通过构造请求发送到nginx,发现nginx会产生400的错误。通过排查,发现nginx生产环境确实存在一些400的错误。
6 总结
至此所有的问题都排查清楚了,下面对排查问题的过程最一些简单的总结:
1 版本升级带来的500异常,是以前一直存在的问题,只是该版本给暴露出来了。
2 导致问题的根本原因可能是网络的抖动等导致的。
3 排查偶发的异常问题,需要耐得住寂寞,仔细排查,如果实在没有思路,那就好好休息一下,整理思路,再继续排查。