网络性能定位

根据tcp协议进行分析

目录

一、SYN_RECV阶段

1.1 确定半连接队列是否有丢包:

 1.2 确定全连接队列是否有丢包现象

二、close_wait

三、TIME_WAIT

四、抓包分析

重要字段:

WireShark出现的常见提示

服务端存在问题的

客户端存在问题的

socket关闭函数:


一、SYN_RECV阶段

        内核在监听套接字的时候,在三次握手时,会创建两个队列,在服务器收到syn 包时,会创建半连接队列,并将这条握手未完成的连接 放到里面,然后回复ack,syn包给客户端,当客户端回复ack时,内核会将这条连接放到全连接队列里,调用accept就是将连接从全连接队列里取出

如果半连接队列或者全连接队列满了,则可能发生丢包行为

1.1 确定半连接队列是否有丢包:

dmesg | grep "TCP: drop open request from"

  半连接队列的连接数量也可以通过netstat命令统计SYN_RECV状态的连接得知。因为在3次握手时,收到syn包的连接的状态是SYN_RECV状态,而整个状态的持续时间是很短的,如果用netstat发现SYN_RECV状态的连接非常多,则说明半连接队列可能满了

netstat -ant|grep SYN_RECV|wc -l

        半连接队列的大小由/proc/sys/net/ipv4/tcp_max_syn_backlog控制,Linux的默认是1024

        当服务端发送SYN_ACK后将会开启一个定时器,如果超时没有收到客户端的ACK,将会重发SYN_ACK包。重传的次数由/proc/sys/net/ipv4/tcp_synack_retries控制,默认是5次

 1.2 确定全连接队列是否有丢包现象

netstat -s

netstat -s | egrep "listen|LISTEN" 
// 全连接队列溢出次数
667399 times the listen queue of a socket overflowed 
// 半连接队列溢出次数
667399 SYNs to LISTEN sockets dropped

ss -lnt

[root@mcs opt]# ss -lnt
State      Recv-Q Send-Q                        Local Address:Port                                       Peer Address:Port              
LISTEN     0      100                                       *:8080                                                  *:*

 在listen状态下,Send-Q表示全连接队列大小的最大值,Recv-Q表示全连接队列的使用大小,超过最大值则会溢出。

应用进程处理包缓慢,持续小于 网卡的接包速度的话,将导致全连接队列很快就满了,导致丢包

二、close_wait

服务端如果出现大量close_wait的话:

这个状态是由于客户端关闭了socket连接,发送了FIN报文,服务端也发送了ACK报文,此时客户端处于FIN_WAIT_2状态,服务端处于CLOSE_WAIT状态。并且可能存在服务端没有发送第二个FIN报文导致的。出现大量close_wait。

曾经遇到的问题:

        首先,我这边的大部分请求都需要查询数据库,我的数据库连接池设置的最大连接数是100,所以每一个请求创建了一个连接,等到100个请求就把连接池占满了,但是处理servlet的那个线程并没有释放这个连接,于是接下来的请求再去创建数据库连接的时候就会一直阻塞在那里,这里我所用的是DBCP作为连接池的,它的实现好像是使用apache的objectPool来实现的,如果没有可用的连接对象会导致线程等待,好了,servlet由于得不到数据库连接而阻塞了,这个客户端的请求就一直等待,客户端使用httpclient设置了5s的请求超时时间,那么超时之后就会抛出异常,关闭连接,关闭连接导致客户端发送了FIN报文,我这边的TCP/IP返回了ACK报文,但是由于处理请求的线程还处于阻塞的状态,所以当前的连接状态时CLOSE_WAIT。

三、TIME_WAIT

           参考TCP四次挥手原理,主动关闭连接的一方会出现 TIME_WAIT 状态,等待的时长为 2MSL(约1分钟左右)

        原因是:主动断开的一方回复 ACK 消息可能丢失,TCP 是可靠的传输协议,在没有收到 ACK 消息的另一端会重试,重新发送FIN消息,所以主动关闭的一方会等待 2MSL 时间,防止对方重试,这就出现了大量 TIME_WAIT 状态(参考: 四次挥手的最后两次)

需要注意:

1.每一个 time_wait 状态,都会占用一个「本地端口」,上限为 65535(16 bit,2 Byte);

2.当大量的连接处于 time_wait 时,新建立 TCP 连接会出错,address already in use : connect 异常

time_wait 状态的影响:

  • TCP 连接中,「主动发起关闭连接」的一端,会进入 time_wait 状态
  • time_wait 状态,默认会持续 2 MSL(报文的最大生存时间),一般是 2x2 mins
  • time_wait 状态下,TCP 连接占用的端口,无法被再次使用
  • TCP 端口数量,上限是 6.5w(65535,16 bit)
  • 大量 time_wait 状态存在,会导致新建 TCP 连接会出错,address already in use : connect 异常

2.现实场景:

  • 服务器端,一般设置:不允许「主动关闭连接」
  • 但 HTTP 请求中,http 头部 connection 参数,可能设置为 close,则,服务端处理完请求会主动关闭 TCP 连接
  • 现在浏览器中, HTTP 请求 connection 参数,一般都设置为 keep-alive
  • Nginx 反向代理场景中,可能出现大量短链接,服务器端,可能存在

3.解决办法:

  • 服务器端允许 time_wait 状态的 socket 被重用
  • 缩减 time_wait 时间,设置为 1 MSL(即,2 mins)

四、抓包分析

重要字段:

序号(sequence number):seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。

确认号(acknowledgement number):ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,ack=seq+1。

标志位(Flags):共6个,即URG、ACK、PSH、RST、SYN、FIN等。具体含义如下:

URG:紧急指针(urgent pointer)有效。

ACK:确认序号有效。(为了与确认号ack区分开,我们用大写表示)

PSH:接收方应该尽快将这个报文交给应用层。

RST:重置连接。

SYN:发起一个新连接。

FIN:释放一个连接。

WireShark出现的常见提示

Packet size limited during capture:标记了的包没抓全
TCP Previous segment not captured:Wireshark 发现后一个包的 Seq 大于 Seq+Len,就知道中间缺失了一段
TCP ACKed unseen segment:发现被 Ack 的那个包没被抓到,就会提示。
TCP Out-of-Order:后一个包的 Seq 号小于前一个包的 Seq+Len 时。
TCP Dup ACK:当乱序或丢包发生时,接收方会收到一些 Seq 号比期望值大的包。没收到一个这种包就会 Ack 一次期望的 Seq 值,提现发送方。
TCP Fast Retransmission:三次DUP ACK之后出发快速重传。(发送端后端观测,前端抓包看一个Dup ACK就发出了,应该是有缓存,3个DUP ACK之后才真正发出)
TCP Retransmission:发送方只好等到超时了再重传。没有收到ack会触发重传机制。
TCP zerowindow:0窗口,没法再收。
TCP window Full:窗口耗尽。没法再发!
Time-to-live exceeded:分片无法正常组装
 

服务端存在问题的

        从抓包文件中,发现760054号报文发生了超时重传,如果客户端发了包,但是服务端没有回应ack消息就会触发超时重传,重传之后,客户端也没有收到服务端的消息,并且可以看到发送挥手信号和前一个正常发送的包之间刚好是隔了差不多200ms,而200ms正是客户端设置的超时时间,应用层触发超时后,将调用close方法关闭链接,所以在760055号包里 客户端发送了一个fin 挥手信号代表客户端要关闭链接了。 客户端发送fin信号挥手之后呢,服务端才发来携带数据的ack消息,不过由于此时客户端已经处于要关闭状态,所以直接发送rst信号了。

        抓包中出现大量TCP Dup Ack 的消息,客户端一直在向端口为6379的服务端发送ack的序号为 13364573,代表客户端已经接收到服务端序号13364573之前的包了,然而服务端连续发送的包序号seq都大于了13364573 ,所以客户端认为服务端序号seq是13364573的包丢了,所以随着服务端每一次发送消息过来,都告诉服务端,我应该接收序号是13364573开始的包,赶紧发送过来。

        最终在1777232号包,客户端又一次发送了TCP Dup Ack 消息,催促服务端赶紧把丢掉的包发过来,不过这次服务端连回应都不回应了,最终触发了客户端应用层200ms的超时时间,调用close方法关闭了连接。所以在1778166号包里,可以看到客户端发送fin挥手信号,1778166 号包的发送时间和1777232号包的发送时间正式相隔了200ms

首先看第一个红色箭头处,也就是911752号包,它被wireshark标记为 Tcp Previous segment not captured,表示这个包之前的包没有被捕获到,说明这个包seq序号之前的包存在丢包情况。发现它前一个包也就是911751号包也是服务端发来的包,并且next seq 是18428124,说明911751号包下一个包的seq应该是18428124,但是911752的seq是18429584,进一步说明 来自服务端的包序号在18428124到18429584之间的包存在丢包情况

接着是客户端对911751号包的ack消息,说明序号是18428124之前的包已经全部接收到。然后接受到了911754号这个来自服务端的包,并且这包的开始seq序号是18433964,而最近一次来自服务端的911752号包的next seq是18432504,说明在18432504 和18433964之间,也存在服务端的丢包情况,所以911754号包也被标记为了Tcp Previous segment not captured。

接下来就是服务端重传包,客户端继续回应Ack的过程,但是这个过程直到914025号时就停止了,因为整个读取服务端响应的过程从开始读 到当前时间已经达到了应用层设置的500ms,所以在应用层直接就关闭掉了这个链接了。


客户端存在问题的

        在看最后,close方法是发送rst信号吗,正常不应该是fin信号? 非也,close方法如果关闭的时候,连接读缓冲区的数据还有未被应用程序读取的话,那么此时close方法的调用会发送rst信号 

        问题的确是出在客户端了,并且看上去像是客户端来不及读取服务端的消息。看到这里,其实我心里已经百分之八九十确定是cpu的使用率达到瓶颈了。

socket关闭函数:

1、close()

close只有在引用计数为0时,才会真正调用close(),否则只是引用计数减1 。

调用close(),系统会尝试发送完内核缓冲区内所有数据,然后才会发送FIN。

2、shutdown()

shutdown不理会引用计数和内核缓冲区内的剩余待发数据包,直接发送FIN。

shuwdown可以只关闭套接字某个方向的连接,例如关闭发送,关闭接收,或两者都关闭。

3、让套接字直接发送RST,从而没有FIN的发送,接收方返回ECONRESET错误,连接直接关闭。

RST在TCP协议中表示复位,用来异常的关闭连接。

发送RST包关闭连接时,不必等缓冲区的包都发出去,直接就丢弃缓冲区的包发送RST包,接收端接收到RST包以后,也不必发送ACK包确认。

参考:

TCP的全连接和半连接队列

一次排查某某云上的redis读超时经历

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/13269.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

机器视觉工程师必须知道机器视觉精度要思考哪些

​在和客户交流项目技术要求,这个项目,我要求的精度是0.01mm? 第一个问题:什么是精度? 精度要求0.01mm: 1.视觉重复性极差?静态?动态? 2.视觉与第三方相关性差异?极差?相关性系数? 3.整体系统误差?机械重复性误差? 4.产品尺寸公差? 第二个问题:精度与公差…

【杂凑算法篇】密码杂凑算法的安全强度

【杂凑算法篇】密码杂凑算法的安全强度 杂凑(哈希)算法安全强度—【蘇小沐】 文章目录 【杂凑算法篇】密码杂凑算法的安全强度(一)安全强度(Security Strength)(二)杂凑算法的安全强度与对比总…

计算机网络笔记(方老师408课程)(持续更新)

文章目录 前言互联网概述互联网发展的三个阶段互联网标准化机构 互联网的组成边缘部分的通信方式核心部分的交换方式 我国计算机网络的发展计算机网络的类别计算机网络的性能速率、带宽、吞吐量时延时延带宽积往返时间RTT(Round-Trip Time)利用率非性能特…

【Linux】进程状态

文章目录 📖 前言1. 父进程与子进程2. fork函数创建子进程2.1 认识fork函数:2.2 fork函数两个返回值的原因:2.3 fork函数的返回值意义: 3. 进程状态3.1 运行状态(R):3.2 终止状态(X&…

FPGA基于SFP光口实现10G万兆网UDP通信 10G Ethernet Subsystem替代网络PHY芯片 提供工程源码和技术支持

目录 1、前言2、我这里已有的UDP方案3、详细设计方案4、vivado工程详解5、上板调试验证并演示6、福利:工程代码的获取 1、前言 目前网上的fpga实现udp基本生态如下: 1:verilog编写的udp收发器,但不带ping功能,这样的代…

Spring AOP核心概念与操作示例

AOP 核心概念 还记得我们Spring有两个核心的概念嘛?一个是IOC/DI,另一个是AOP咯。 先来认识两个概念: AOP(Aspect Oriented Programming)面向切面编程;作用:在不惊动原始设计的基础上为其进行功能增强,类…

《springboot实战》第六章 实现自定义全局异常处理

前言 springboot实现自定义全局异常处理,以及统一返回数据。 1、分析 首先,实现全局异常的流程 从图中可以看到,实现全局异常会需要这样几个类: 自定义异常接口类自定义异常枚举类自定义异常类自定义异常处理类自定义全局响应…

ROS学习第十二节——话题通信控制小乌龟

1.基操一下 首先打开小乌龟程序和键盘控制程序 rosrun turtlesim turtlesim_node rosrun turtlesim turtle_teleop_key 查看话题列表 rostopic list 打开计算图查看具体是那个话题在起作用 rqt_graph 从上图可以看到两个节点之间的话题是 /turtle1/cmd_vel 使用以下命令获…

linux及openEuler破解root密码

第一步:开机的时候按键盘的字母 E 键, 进入引导模式 第二步:进入引导模式 :找到linux这一行,按键盘上的end 键,跳转到行尾,输入: init/bin/sh 修改完后,按键盘上的 ctr…

哪种无线耳机音质最好?盘点2023四款好音质蓝牙耳机

随着蓝牙技术的发展,近几年人们对于蓝牙耳机的需求也在不断增加。但,蓝牙耳机自始至终都是用来听的,所以音质对于一款蓝牙耳机来说还是很重要的。下面,我来给大家推荐四款好音质蓝牙耳机,可以当个参考。 一、南卡小音舱…

JavaEE-轻松了解网络原理之TCP协议

目录 TCP协议TCP协议数据格式TCP原理确认应答超时重传连接管理三次握手四次挥手 滑动窗口流量控制拥塞控制延迟应答捎带应答面向字节流异常问题 TCP协议 TCP,即Transmission Control Protocol,传输控制协议. TCP协议数据格式 16位源端口号与16位目的端…

Doris(8):数据导入(Load)之Insert Into

Insert Into 语句的使用方式和 MySQL 等数据库中 Insert Into 语句的使用方式类似。但在 Doris 中,所有的数据写入都是一个独立的导入作业。所以这里将 Insert Into 也作为一种导入方式介绍。 主要的 Insert Into 命令包含以下两种; INSERT INTO tbl S…

微服务 - Redis缓存 · 数据结构 · 持久化 · 分布式 · 高并发

一、分布式解决 Session 的问题 在单站点中,可以将在线用户信息存储在Session中,随时变更获取信息;在多站点分布式集群如何做到Session共享呢?架设一个Session服务,供多服务使用。 频繁使用的数据存在DB端&#xff0…

如何使用镭速保护云存储数据安全

近年来,随着云计算的发展,远程系统上的数据存储变的越来越重要。云存储是一个以数据存储和管理为核心的云计算系统,给我们提供了一种全新的数据信息存储模式。但是,可以从全球任何地方访问和检索相同的数据。所需要的只是一个简单…

protobuf序列化原理、安装与应用

目录 protobuf序列化 protobuf的原理 protobuf 的安装 编译message文件 应用protobuf protobuf序列化 protobuf是一种比json和xml等序列化工具更加轻量和高效的结构化数据存储格式,性能比json和xml真的强很多,毕竟google出品。 官网:https:…

第八章 法律关系

目录 第一节 法律关系的概念 一、法律关系的定义与特征 二、法律关系的种类 (一)纵向(隶属)的法律关系和横向(平权)的法律关系 (二)单向(单务)法律关系、双…

Dear ImGui结合CMake实现基于GLFW和OpenGL3的入门级hello world代码

Dear ImGui结合CMake实现基于GLFW和OpenGL3的入门级hello world代码 如需转载请标明出处:https://blog.csdn.net/itas109 技术交流:129518033 环境: OS: windows 10 / Ubuntu 22.04 imgui: 1.89.5 glw: 3.3.8前言 Dear ImGui 是一个 用于…

outlook邮箱pc/mac客户端下载 含最新版

新的 Outlook for Windows or mac 为 Outlook 应用带来了最新功能、智能辅助功能和新的新式简化设计。 你可以根据自己的风格定制它,并使用新的 Outlook for Windows/mac 执行更多操作! 览版,与我们一起开始旅程,并帮助我们塑造新…

leetcode142. 环形链表 II

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数…

python 打包新方案

首先是打包一个最简单的python 代码使用 pyinstaller import os #直接读取文件获得python.exe 路径 # 待执行python路径 with open("path_run.txt","r",encoding"utf-8") as f:python_exe,pyf.readlines() os.system("{} {}".format(p…