9

TCP全队列溢出问题排查过程

 3 years ago
source link: https://zhuanlan.zhihu.com/p/343926395
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

简介: 记一次TCP全队列溢出问题排查过程

qeqQ3q.png!mobile

1. 前言

本文排查的问题是经典的TCP队列溢出问题,因TCP队列问题在操作系统层面没有明显的指标异常,容易被忽略,故把排查过程分享给大家。

2. 问题描述

A服务调用B服务接口超时,B服务主机IOWAIT高,具体超时情况分为两种:

  • A服务的请求在B服务日志中可查到,但B服务的响应时间超过了A服务的等待超时时间3S。
  • A服务的请求在B服务日志中无法查到。

3. 问题分析

此种超时请求集中在很短的一段时间(通常在2分钟之内),过后便恢复正常,所以很难抓到问题现场分析原因,只能搭建测试环境,A服务持续请求B服务,在B服务主机上通过DD命令写入大量数据造成主机IOWAIT高,同时通过TCPDUMP在两端抓包分析。

部分服务超时日志:

  • 服务A:Get http:// xxx &id=593930: net/http: request canceled (Client.Timeout exceeded while awaiting headers)
  • 服务B: "GET xxx&id=593930 HTTP/1.1" 200 64 "-" "Go-http-client/1.1" "-" "-" 165000(单位微秒)

服务A发起请求3S后没有收到服务B响应,断开连接,服务B日志显示处理时长为0.165S,远低于3S,服务A侧看服务B的响应时间为网络传输时间、TCP队列排队时间及服务B应用程序处理时间之和,因为是内网测试,网络传输时间可以忽略,主要排查方向应为TCP队列排队时间。

4. 抓包数据分析

情景1:服务A及服务B均有连接日志打印。

服务A端数据包分析:

09:51:43.966553000 服务A发起 GET请求的数据包如下:

baEZzqA.png!mobile

图1:服务A发起GET请求

09:51:46.966653000 服务A发起 GET请求3s(即服务A设置的等待超时时长)后,因未收到服务B响应,服务A向服务B发起FIN主动断开连接。

nqY7fmi.png!mobile

图2:服务A等待超时主动断开连接

09:51:59.958195000 服务A发起http请求16s后收到服务B的http响应报文,因服务A已主动关闭该连接,故直接回复RST。

nYvuQn.png!mobile

图3: 服务B16s后响应

服务B端数据包分析:

09:51:44.062095000 服务B收到服务A发送的http请求包。

BvA3qyN.png!mobile

图4:服务B收到服务A的请求

09:51:59.936169000 服务B响应服务A,服务B从接收到http请求报文至响应http请求总用时约为15s多,但服务B打印的日志响应时长约为0.165s。

qI3yIf.png!mobile

图5:服务B15S后响应

EN77feF.png!mobile

图6:服务B日志显示响应时间0.165s

情景2:服务A有连接日志,服务B无连接日志。

服务A端数据包分析:

09:51:43.973791000 服务A向服务B发送一个http请求数据包,随后收到服务B重传的第二次握手的syn+ack包,超过3s未收到服务B的http响应后断开连接。

NzIfUn3.png!mobile

图7:服务B重传syn+ack

服务B端数据包分析:

服务B重传了第二次握手的syn+ack包,收到服务A的http请求,服务B忽略,未响应,服务A等待超时后断开了连接。

EBn6RrR.png!mobile

图8: 服务B忽略服务A请求

5. 根因分析

TCP在三次握手过程中内核会维护两个队列:

  • 半连接队列,即SYN队列
  • 全连接队列,即ACCEPT队列
2MN3Evy.png!mobile

图9:TCP队列

TCP三次握手过程中,第一次握手server收到client的syn后,内核会把该连接存储到半连接队列中,同时回复syn+ack给client(第二次握手),第三次握手时server收到client的ack,如果此时全连接队列未满,内核会把连接从半连接队列移除,并将其添加到 accept 队列,等待应用进程调用 accept 函数取出连接,如果全连接队列已满,内核的行为取决于内核参数tcp_abort_on_overflow:

  • tcp_abort_on_overflow=0,server会丢弃client的ack。
  • tcp_abort_on_overflow=1,server 会发送 reset 包给 client。

默认值是0。

情景1的抓包数据显示连接已经进入全连接队列,但是服务B日志显示的连接时间晚了15S多,说明连接在队列里等待了15S后才被应用处理。

情景2的抓包数据显示全连接队列已溢出,内核根据tcp_abort_on_overflow的值为0丢弃了服务A的ack,超过了服务A的超时等待时间。

结论:服务B主机在IO达到瓶颈的情况下,系统CPU时间主要消耗在等待IO响应及处理软中断上,服务B应用程序获取的CPU时间有限,无法及时调用 accept 函数把连接取出并处理,导致TCP全队列溢出或队列等待时间过长,超过了服务A的超时时间。

6. 如何观察和调整tcp全队列

73e63eF.png!mobile

图10: TCP全队列观察方法

当连接处于listen状态时:

  • Recv-Q:目前全连接队列的大小
  • Send-Q:目前全连接最大队列长度

当Recv-Q > Send-Q时表示全队列溢出,可通过执行netstat -s | grep "overflowed"命令观察溢出情况,查看累计溢出次数,如果需观察一段时间内的全队列溢出情况,建议使用监控系统采集数据,比如prometheus。

mI3qaqF.png!mobile

图11: TCP队列溢出监控

TCP 全连接队列最大值取决于min(somaxconn, backlog),其中:

  • somaxconn可通过内核参数/proc/sys/net/core/somaxconn设置,默认值是128。
  • backlog是 listen(int sockfd, int backlog) 函数中的 backlog 大小,Nginx 默认值是 511,可以通过修改配置文件设置其长度。

7. 结语

本次问题,因为服务对成功率要求很高,所以先通过调大服务B主机/proc/sys/net/core/somaxconn参数值及服务A的超时时间来缓解超时问题,暂时保证了接口成功率。但要从根本上解决问题,仍需解决诱因io瓶颈,因为服务B主机挂载的共享sas存储集群上有其他客户的主机偶尔io很大,影响了整个集群的性能。为解决此问题,更换为独享的ssd盘,并通过blktrace+fio分析,将io调度算法修改为noop,io性能明显提升,TCP队列溢出问题也随之解决。

我们是阿里云智能全球技术服务-SRE团队,我们致力成为一个以技术为基础、面向服务、保障业务系统高可用的工程师团队;提供专业、体系化的SRE服务,帮助广大客户更好地使用云、基于云构建更加稳定可靠的业务系统,提升业务稳定性。我们期望能够分享更多帮助企业客户上云、用好云,让客户云上业务运行更加稳定可靠的技术,您可用钉钉扫描下方二维码,加入阿里云SRE技术学院钉钉圈子,和更多云上人交流关于云平台的那些事。

版权声明: 本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。


Recommend

  • 67
    • 微信 mp.weixin.qq.com 5 years ago
    • Cache

    TCP/IP的底层队列

  • 44
    • www.tuicool.com 4 years ago
    • Cache

    [译] TCP的SYN队列和Accept队列

    首先我们必须明白,处于“LISTENING”状态的TCP socket,有两个独立的队列: SYN队列(SYN Queue) Accept队列(Accep...

  • 40
    • network.51cto.com 4 years ago
    • Cache

    TCP的SYN队列和Accept队列

    首先我们必须明白,处于“LISTENING”状态的TCP socket,有两个独立的队列: SYN队列(SYN Queue) Accept队列(Accept Q...

  • 11
    • studygolang.com 4 years ago
    • Cache

    TCP SYN队列与Accept队列详解

    李乐 尽信书,不如无书。 纸上得来终觉浅,绝知此事要躬行。 实验现象依赖于系统(如下)以及内核参数(附录);一切以实验结果为准。 cat /proc/version Linux version 3.10.0-693.el7.x86_64

  • 16

    大量生成字节码导致元空间溢出问题排查 | PerfMa应用性能技术社区文章>大量生成字节码导致元空间溢出问题排查大量生成字节码导致元空间溢出问题排查

  • 9
    • blog.csdn.net 3 years ago
    • Cache

    TCP协议三次握手过程分析

    TCP协议三次握手过程分析

  • 7
    • www.cxyxiaowu.com 2 years ago
    • Cache

    详细说下 TCP 四次挥手的过程?

    详细说下 TCP 四次挥手的过程?-吴师兄学编程 当前位置:吴师兄学编程 > 计算机网络 > 详细说下 TCP 四次挥手的过程? ...

  • 4
    • www.cxyxiaowu.com 2 years ago
    • Cache

    详细说下 TCP 三次握手的过程?

    详细说下 TCP 三次握手的过程?-吴师兄学编程 当前位置:吴师兄学编程 > 计算机网络 > 详细说下 TCP 三次握手的过程? ...

  • 5
    • jasonkayzk.github.io 1 year ago
    • Cache

    排查tcp连接数不断升高的问题

    最近发生了一件“怪事”,我的服务器TCP连接数每天都在以一个速度上涨,这肯定是哪里一直在进行长连接没有关; 最近一直比较忙,今天晚上抽空看了一下,解决了; 排查tcp连接数不断升高的问题

  • 6
    • acejoy.com 5 months ago
    • Cache

    排查 Celery 队列的任务问题

    排查 Celery 队列的任务问题 2023/9/26 0 Comments 198 Views 0 Times 近日使用 Celery 队列系统构造服务,遇到队列任务无法执行的问题,经过排查找到原因,记录一下,防止日后忘记。Celery 是一...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK