IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 面试官:生产环境发生问题,你一般怎么排查?(网络篇) -> 正文阅读

[系统运维]面试官:生产环境发生问题,你一般怎么排查?(网络篇)

请添加图片描述

网络篇

TCP报文格式

TCP协议包的格式如下所示,从第4行可以看到有6个标记位。这6个标记位的含义如下
在这里插入图片描述
【源端口】-16bit
【目的端口】-16bit
【序号】- 32bit
每一个TCP报文段都会有一个序号,序号字段的值为本报文段所发送的数据的第一个字节的序号。这是因为TCP是面向连接的可靠服务,其每一个字节都会对应一个序号,通过序号来确保服务的可靠性和有序性。例如一段报文序号seq是201,报文长度为100,则下一个报文段的序号为301(201+100)
【确认号】- 32bit
确认号,是期望收到对方的下一个报文段的数据的第一个字节的序号。
【数据偏移】- 4bit
其实它本质上就是“首部长度”,因为“数据偏移”是指TCP报文段的数据部分的起始处距离TCP报文段的起始处的距离。(仍然很拗口,但相信你能明白)。
数据偏移总共占4bit,因此最大能表示的数值为15。而数据偏移的单位是“4字节”,此处的设计和IP数据报的设计是完全相同的,所以说TCP报文段首部的长度最长为15×4=60字节,且首部长度必须为4字节的整数倍。
【保留字段】- 6bit
这6bit在标准中是保留字段

接着是数据状态标志位,分为如下6种(1是开启,0是关闭)

【紧急字段URG】- 1bit
当URG=1时,表示报文段中有紧急数据,应尽快传送。
【确认字段ACK】- 1bit
当ACK=1时,表示确认,且确认号有效;当ACK=0时,确认号字段无效。
【推送字段PSH】- 1bit
当PSH=1时,则报文段会被尽快地交付给目的方,不会对这样的报文段使用缓存策略。
【复位字段RST】- 1bit
当RST为1时,表明TCP连接中出现了严重的差错,必须释放连接,然后再重新建立连接。
【同步字段SYN】- 1bit
当SYN=1时,表示发起一个连接请求。
【终止字段FIN】- 1bit
用来释放连接。当FIN=1时,表明此报文段的发送端的数据已发送完成,并要求释放连接。

【窗口字段】- 16bit
此字段用来控制对方发送的数据量,单位为字节。
一般TCP连接的其中一端会根据自身的缓存空间大小来确定自己的接收窗口大小,然后告知另一端以确定另一端的发送窗口大小。
【校验和字段】- 16bit
这个校验和是针对首部和数据两部分的。
【紧急指针字段】- 16bit
紧急指针是一个正的偏移量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号
【选项】- 长度可变
可选的。最常见的可选字段是最长报文大小
【填充】
填充是为了使TCP首部为4字节(32bit)的整数倍

【TCP数据部分】
可选的,当连接建立或中止时,报文段只有TCP首部

发送速率

通过发送速率我们就能确定系统的流量大小。如果还需要计算发送数据量的大小,就需要换算一下。一般情况下我们不需要精确计算数据传输的大小,单位相同直接除8即可

常用数据量单位
一个比特就是二进制数据中的一个1或0
1Byte = 8 bit
KB = 210B
MB = KKB = 220B
GB = K
MB = 230B
TB = K*GB = 240B

常用速率单位
kb/s = 103b/s (bps) (一秒传输1000个比特)
Mb/s = kkb/s = 106b/s (bps)
Gb/s = k
Mb/s = 109b/s (bps)
Tb/s = k*Gb/s = 1012b/s (bps)

有一个待发送的数据块,大小为100MB,网卡的发送速率为100Mbps,则网卡发送完该数据需要多长时间
在这里插入图片描述
8mbps=1mb(每秒传输的大小为1mb)
8gbps=1gb(每秒传输的大小为1gb)

三次握手

三次握手的过程其实在我们生活中经常遇到,尤其是打电话,下面这个场景非常常见

A: 你好,我是A,你能听到我说话吗?
B:你好A,我是B,你能听到我说话吗?
A:可以的

三次握手能让Server和Client都确认双方发送和接收正常
第一次握手:Client什么都不能确认,Server确认对方发送正常
第二次握手:Client确认了自己发送和接收正常,对方发送和接收正常。Server确认了自己接收正常,对方发送正常
第三次握手:Client确认了自己发送和接收正常,对方发送和接收正常。Server端确了自己发送和接收正常,对方发送和接收正常

二次握手可以吗?
不可以,因为Server端无法确认自己发送正常和对方接收正常

四次握手可以吗?
当然可以,但是没必要。保证Server和Client都正常发送和接收就可以了

请添加图片描述
TCP的三次握手流程如下

  1. 启动服务端,然后服务端主动监听某个端口,处于LISTEN(监听)状态
  2. 第一次握手,客户端向服务端发送请求连接包文,报文首部SYN标志位为1,同时设置序列号seq=x(随机数);发出后,客户端进入SYN_SENT(SYN报文不携带数据)
  3. 第二次握手,服务端收到客户端的请求后,需要进行确认,将响应报文中ACK标志位设置为1,将确认号ack设置为第一步请求序列号seq+1(ack=x+1),将SYN标志位设置为1,即SYN+ACK包,包序号seq=y,服务端进入SYN_RCVD状态
  4. 第三次握手,客户端收到来自服务端的SYN+ACK包,发送一个ACK确认包,ACK=1,seq=x+1(第一步的序号x递增),ack=y+1(序号为y及之前的数据已收到,期待收到序号y+1之后的数据)

TCP队列溢出

当我们基于TCP进行socket编程时,编程模型如下所示。
在这里插入图片描述
我们把三次握手的过程放在编程模型中,来看2个重要的队syns queue(半连接队列)和accept queue(全连接队列)
在这里插入图片描述

  1. server端接收syn请求,创建socket存储于syns queue,并向客户端返回syn+ack
  2. server端接收到第三次握手的ack,socket状态更新为ESTABLISHED,同时将socket移动到accept queue,等待应用程序执行accept()

我们可以通过netstat或者ss命令查看socket信息

  1. 当socket处于LISTEN状态时,Send-Q为accept queue的最大长度,Recv-Q为accept queue中等待应用程序accept()的socket数目
  2. 当socket处于ESTABLISHED状态时,Send-Q与Recv-Q分别表示socket发送缓冲区与接收缓冲区数据大小

请添加图片描述
当我们通过tcp发送数据的时候,数据并不是直接通过网络发送完就完事了,而是先将数据发送到发送缓冲区,然后再发送到对方的接收缓冲区。当相应的数据返回ack后才会从发送缓冲区中删除(这里涉及到滑动窗口协议,有兴趣的小伙伴可以参考一下其他书籍)当发送缓冲区满时,发送端将会阻塞,不能发送数据。如果接收端一直不读取数据,不发送ack,也会导致发送方无法发送数据

所以当请求处理比较慢时,可以看一下Send-Q和Recv-Q是否有大量积压。

socket处于ESTABLISHED状态

[root@VM-0-14-centos ~]# ss
Netid State      Recv-Q Send-Q                                     Local Address:Port                                                      Peer Address:Port                
u_str ESTAB      0      0                                                      * 179546845                                                            * 179546846            
u_str ESTAB      0      0                                                      * 60692020                                                             * 0   

socket处于LISTEN状态

[root@VM-0-14-centos ~]# ss -lnt
State       Recv-Q Send-Q                                         Local Address:Port                                                        Peer Address:Port              
LISTEN      0      50                                                         *:3306                                                                   *:*                  
LISTEN      0      128                                                        *:80                                                                     *:*   

当我们机器的并发量很高时,accept queue可能会出现不够用的情况,这时就有可能出现类似connection reset 或 connection timeout 异常,这个取决于机器上tcp_abort_on_overflow的设置,不同的值服务端有不同的处理策略

tcp_abort_on_overflow为0:全连接队列满时,server端扔掉client发过来的ack,那么client会重新发送ack,直到超时,这时客户端就会看到connection timeout的错误

tcp_abort_on_overflow为1:全连接队列满时,server端发送一个reset包给client,表示连接出现错误,这时客户端就会看到
connection reset 的错误

查看服务器处理accept queue队列满时的处理机制

[root@VM-0-14-centos ~]# cat /proc/sys/net/ipv4/tcp_abort_on_overflow
0

如何设置sync queue和accept queue的大小

sync queue 队列长度由 /proc/sys/net/ipv4/tcp_max_syn_backlog 指定

accept queue 队列长度 为 min(somaxconn, backlog)

somaxconn 的值可以在配置文件/proc/sys/net/core/somaxconn中直接修改
backlog 的值是在创建socket时传入的

// 在java中的设置方式如下
public ServerSocket(int port, int backlog)

如何查看queue的溢出情况?

查看syns queue溢出

[root@VM-0-14-centos ~]# netstat -s | grep LISTEN
    190 SYNs to LISTEN sockets dropped

查看accept queue溢出

[root@VM-0-14-centos ~]# netstat -s | grep TCPBacklogDrop
    TCPBacklogDrop: 23

RST异常

TCP断开连接的方式有两种

  1. 连接正常关闭时双方会发送FIN,然后经历四次挥手的过程
  2. 通过RST包异常退出,不会对RST响应ACK

当收到RST包时,表示连接异常关闭,应用中可能会报大量的connection reset / connection reset by peer错误。
当在一个已经关闭的连接上读操作时,会报connection reset。当在一个已关闭的连接上写操作时,会报 connection reset by peer

那么什么时候会发送RST包呢?

  1. 端口不存在,向不存在的端口发送syn请求时,服务端发现这个端口不存在则直接发送一个RST包
  2. 服务端或客户端发生异常(比如程序奔溃了,上面提到的TCP队列溢出),向对端发送RST包,告知另一方连接关闭
  3. 新接收到的tcp报文不在已知的连接中。比如一方网络太差,tcp报文没有到达。此时另一端关闭了连接,然后收到了这个迟迟没有到达的报文,但由于对应的tcp连接已经不存在,就会直接发送一个RST包
  4. 一方长期未收到另一方的确认报文,在一定时间或重传次数后发出RST报文

四次挥手

请添加图片描述

  1. 客户端发送FIN释放连接报文,表示结束连接,seq=u,此时客户端进入FIN_WAIT_1状态
  2. 服务端收到释放连接报文,发出确认报文ACK=1,ack=u+1,seq=v,此时服务端进入CLOSE_WAIT状态,客户端向服务端方向发送的通道关闭了,但是此时服务端若发送数据,客户端依然要接收
  3. 客户端收到服务端的确认请求后,客户端进入FIN_WAIT_2状态,等待服务端发送连接释放报文
  4. 服务端发完最后的数据,向客户端发送FIN连接释放报文,此时序列号seq=u(有可能中间发送了一部分数据),ack和回复ACK报文一致,即ack=u+1,此时服务端进入LAST_ACK状态
  5. 客户端收到服务端的连接释放报文后,发出确认报文ACK=1,ack=w+1,seq=u+1,此时客户端进入TIME_WAIT状态。此时tcp连接还没有释放,必须经过2个MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态
  6. 服务端只要收到客户端发出的确认,立即进入CLOSED状态,同样,撤销TCB后,就结束了这次的TCP连接。

为什么有一个TIME_WAIT(时间等待状态)?

当客户端在FIN_WAIT_2阶段发送ack丢失后,服务端在LAST_ACK阶段会不断重试,导致连接不能正常关闭。如果此时客户端已经关闭则会导致服务端不能正常关闭。如果有一个TIME_WAIT阶段,则可以使本次连接持续时间内所产生的所有报文段从网络中消失
在这里插入图片描述

TIME_WAIT和CLOSE_WAIT

我们经常使用如下命令来查看服务器的连接状态

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

它会显示如下信息

TIME_WAIT 689
CLOSE_WAIT 2
FIN_WAIT1 1
ESTABLISHED 291
SYN_RECV 2
LAST_ACK 1

在这里插入图片描述
常用的三个状态是:ESTABLISHED表示正在通信 、TIME_WAIT表示主动关闭、CLOSE_WAIT表示被动关闭

当服务器保持了大量的TIME_WAIT和CLOSE_WAIT状态的连接,就需要格外注意一下,主动关闭的一方会经过TIME_WAIT阶段,被动关闭的一方会经过CLOSE_WAIT阶段

因为在Linux中进程每打开一个文件(linux下一切皆文件,包括socket),都会消耗一点的内存资源,所以Linux在多个位置都限制了可打开文件描述符的数量,包括系统级,用户级,进程级。

系统级:当前系统可打开的最大数量,通过fs.file-max参数可修改
用户级:指定用户可打开的最大数量,修改/etc/security/limits.conf
进程级:单个进程可打开的最大数量,通过fs.nr_open参数可修改

一旦文件描述符达到上限,新的请求就无法被处理了,接着就是大量Too Many Open Files异常

TIME_WAIT

前面已经提到过,TIME_WAIT一方面是为了丢失的包被后面的连接复用,二是为了在2MSL的时间范围内正常关闭连接,TIME_WAIT的存在会大大减少RST包的出现。

当出现大量TIME_WAIT状态的连接时(一般情况下也比较高,因为有一个2MSL时长),解决思路也很简单,就是让服务器能够快速回收和重用那些TIME_WAIT的资源。我们可以修改一下服务端的内核参数

#表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭
net.ipv4.tcp_tw_reuse = 1
#表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭
net.ipv4.tcp_tw_recycle = 1

CLOSE_WAIT

当CLOSE_WAIT状态的连接很多时,说明没有在ACK后再次发起FIN报文,这种情况往往是由于应用程序写的有问题,如短连接模式,忘记close连接,就不会发出FIN包

三次握手后连接已经建立,但是客户端突然奔溃了怎么办?

首先,从协议设计角度来讲,客户端如果出现故障,服务端肯定不能一直死等客户端,所以考虑这种情况的存在,TCP 协议中服务端有个计时器,每次收到客户端的响应报文都会重置这个计时器,服务端有个超时时间,通常是2个小时,2个小时没收到客户端的数据,服务端会每隔75秒发送探测报文段,连续10次探测报文没响应,认为客户端出现问题,服务器会关闭这个连接。一般程序设计者不会依赖这个机制,2个小时实在太长,框架里面都会自己做连接的检查,无效连接的关闭。

当你使用Netty的时候,可以使用IdleStateHandler来定义心跳策略,设置读超时时间和写超时时间,当相应的时间到了还没收到消息,则会触发相应事件,此时你就可以选择关闭这个连接等策略

参考博客

[1]https://mp.weixin.qq.com/s/9pgV9zC53xWbESrqRKTi8Q
queue的参数
[2]https://www.cnblogs.com/orgliny/p/5780796.html
发送缓冲区和接收缓冲区
[3]https://blog.csdn.net/farmwang/article/details/73520624
[4]https://www.5a3q.com/sex/1489481.html
[5]https://zhuanlan.zhihu.com/p/69217521

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-10-22 11:20:10  更:2021-10-22 11:20:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 20:57:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码