TCP挥手分析Nginx日志
2023/1/1 来源:不详大家好,我是TT。
我们在做一些应用排查的时候,时常会在日志里看到跟TCP有关的报错。比如在Nginx的日志里面,可能就有connctionrstbypr这种报错。“连接被对端rst(重置)”,这个字面上的意思是看明白了。但是,心里不免发毛:
这个rst会影响我们的业务吗,这次事务到底有没有成功呢?这个rst发生在具体什么阶段,属于TCP的正常断连吗?我们要怎么做才能避免这种rst呢?
要回答这类追问,Nginx日志可能就不够用了。
事实上,网络分层的好处是在于每一层都专心做好自己的事情就行了。而坏处也不是没有,这种情况就是如此:应用层只知道操作系统告诉它,“喂,你的连接被rst了”。但是为什么会被rst呢?应用层无法知道,只有操作系统知道,但是操作系统只是把事情处理掉,往内部rst计数器里加1,但也不记录这次rst的前后上下文。
所以,为了搞清楚connctionrstbypr时具体发生了什么,我们需要突破应用层这口井,跳出来看到更大的网络世界。
在应用层和网络层之间搭建桥梁
首先,你需要理解下connctionrstbypr的含义。熟悉TCP的话,你应该会想到这大概是对端(pr)回复了TCPRST(也就是这里的rst),终止了一次TCP连接。其实,这也是我们做网络排查的第一个要点:把应用层的信息,“翻译”成传输层和网络层的信息。
或者说,我们需要完成一件有时候比较有挑战的事情:把应用层的信息,跟位于它下面的传输层和网络层的信息联系起来。
这里我说的“应用层信息”,可能是以下这些:
应用层日志,包括成功日志、报错日志,等等;应用层性能数据,比如RPS(每秒请求数),transactiontim(处理时间)等;应用层载荷,比如HTTP请求和响应的hadr、body等。
而“传输层/网络层信息”,可能是以下种种:
传输层:TCP序列号(SquncNumbr)、确认号(AcknowldgNumbr)、MSS、接收窗口(RcivWindow)、拥塞窗口(CongstionWindow)、时延(Latncy)、重复确认(DupAck)、选择性确认(SlctivAck)、重传(Rtransmission)、丢包(Packtloss)等。
网络层:IP的TTL、MTU、跳数(hops)、路由表等。
可见,这两大类(应用vs网络)信息的视角和度量标准完全不同,所以几乎没办法直接挂钩。而这,也就造成了问题排查方面的两大鸿沟。
应用现象跟网络现象之间的鸿沟:你可能看得懂应用层的日志,但是不知道网络上具体发生了什么。
工具提示跟协议理解之间的鸿沟:你看得懂Wirshark、tcpdump这类工具的输出信息的含义,但就是无法真正地把它们跟你对协议的理解对应起来。
也就是说,你需要具备把两大鸿沟填平的能力,有了这个能力,你也就有了能把两大类信息(应用信息和网络信息)联通起来的“翻译”的能力。这正是网络排查的核心能力。
既然我们是案例实战课程,这些知识从案例里面学,是最高效的方法了。接下来,就让我们一起看两个案例吧。
案例1:connctionrstbypr?
前几年我在UCloud服务的时候,有个客户也是反馈,他们的Nginx服务器上遇到了很多connctionrstbypr的报错。他们担心这个问题对业务产生了影响,希望我们协助查清原因。客户的应用是一个普通的Wb服务,架设在Nginx上,而他们的另外一组机器是作为客户端,去调用这个Nginx上面的Wb服务。
架构简图如下:
前面我说过,单纯从应用层日志来看的话,几乎难以确定connctionrstbypr的底层原因。所以,我们就展开了抓包工作。具体做法是:
我们需要选择一端做抓包,这次是客户端;
检查应用日志,发现没几分钟就出现了connctionrstbypr的报错;
对照报错日志和抓包文件,寻找线索。
我们先看一下,这些报错日志长什么样子:
/12/:49:48[info]#0:*rcv()faild(:Connctionrstbypr)whilsndingtoclint,clint:10...1,srvr:managr.xampl.