一些基本引言的知识点
-
⻦哥在 PHP7 中 把 HashTable 结构体从 72 字节压缩到了 56 字节,表⾯看起来不⼤的优化,实际上是成倍的性能提醒。因为 CPU 在向内存要数据的时候是以 Cache Line 为单位进⾏的,⼀个 Cache Line 是 64 字节。56 字节可以⼀次请求搞定,⽽原来的 72 字节则需要两次。另外就是 L1/L2/L3 的命中率也会提升很多,这个对性能的帮助更⼤。
-
kafka为什么快?
-
顺序读写
-
Memory Mapped Files(mmap),工作原理是直接利用操作系统的 Page 来实现文件到物理内存的直接映射,完成映射之后你对物理内存的操作会被同步到硬盘上(操作系统在适当的时候Async,操作系统会在程序主动调用 Flush 的时候才把数据真正的写到硬盘Sync)。
-
基于 Sendfile 实现Zero Copy,传统 Read/Write 方式进行网络文件传输的方式,硬盘—>内核 buf—>用户 buf—>Socket 相关缓冲区—>协议引擎,当消费者需要数据的时候 Kafka 直接把文件发送给消费者,配合 mmap 作为文件读写方式,直接把它传给 Sendfile
-
批量压缩,系统的瓶颈不是 CPU 或磁盘,而是网络 IO
总结:Kafka 速度的秘诀在于,它把所有的消息都变成一个批量的文件,并且进行合理的批量压缩,减少网络 IO 损耗,通过 mmap 提高 I/O 速度。
写入数据的时候由于单个 Partion 是末尾添加,所以速度最优;读取数据的时候配合 Sendfile 直接暴力输出。
-
-
负载均衡SLB:基于DNS负载均衡、基于硬件负载均衡、基于软件负载均衡
系统调优你所不知道的TIME_WAIT和CLOSE_WAIT
什么是TIME-WAIT和CLOSE-WAIT?
大家知道,由于socket是全双工的工作模式,一个socket的关闭,是需要四次握手来完成的。
- 主动关闭连接的一方,调用close();协议层发送FIN包
- 被动关闭的一方收到FIN包后,协议层回复ACK;然后**被动关闭的一方,进入CLOSE_WAIT状态,**主动关闭的一方等待对方关闭,则进入FIN_WAIT_2状态;此时,主动关闭的一方 等待 被动关闭一方的应用程序,调用close操作
- 被动关闭的一方在完成所有数据发送后,调用close()操作;此时,协议层发送FIN包给主动关闭的一方,等待对方的ACK,被动关闭的一方进入LAST_ACK状态;
- 主动关闭的一方收到FIN包,协议层回复ACK;此时,主动关闭连接的一方,进入TIME_WAIT状态;而被动关闭的一方,进入CLOSED状态
- 等待2MSL时间,主动关闭的一方,结束TIME_WAIT,进入CLOSED状态
结论:
-
主动关闭连接的一方 - 也就是主动调用socket的close操作的一方,最终会进入TIME_WAIT状态
-
被动关闭连接的一方,有一个中间状态,即CLOSE_WAIT,因为协议层在等待上层的应用程序,主动调用close操作后才主动关闭这条连接
-
TIME_WAIT会默认等待2MSL时间后,才最终进入CLOSED状态;
-
在一个连接没有进入CLOSED状态之前,这个连接是不能被重用的!
MSL不同系统的默认值
- Windows : MSL = 2 min
- linux(Ubuntu, CentOs) : MSL = 60s
- Unix : MSL = 30s
一台主机上只能保持最多 65535 个 TCP 连接吗?
-
是四元组(源IP,源PORT,目标IP,目标PORT),在一台主机上,只要这个四元组不重复
-
文件描述符
-
系统资源(主要是内存)
Socket连接到底是个什么概念?
socket就是一个 五元组,包括:
- 源IP
- 源端口
- 目的IP
- 目的端口
- 类型:TCP or UDP
第二个问题,TIME_WAIT有什么用?
就是为了解决网络的丢包和网络不稳定所带来的其他问题
- 重用:前面一个连接上的数据被后面的一个连接错误的接收
[xielianjun@set-xr-mdm-schedule-test01 ~]$ netstat -a | grep TIME_WAIT | wc -l
44
RTO RTT
- RTT(Round Trip Time):一个连接的往返时间,即数据发送时刻到接收到确认的时刻的差值;
- RTO(Retransmission Time Out):重传超时时间,即从数据发送时刻算起,超过这个时间便执行重传, RTO协议实现值最小1s
RTT 和 RTO 的关系是:由于网络波动的不确定性,每个RTT都是动态变化的,所以 RTO 也应随着 RTT 动态变化。
为何客户端突然出现大量TIME_WAIT堆积
问题场景:原来客户端直接访问后端Web服务器,TIME_WAIT数量非常少。现在引入了7层SLB来实现对后端服务器的负载均衡。客户端SLB访问后端服务器,但是发现客户端的TIME_WAIT状态的socket很快累积到4000多个,并且客户反映没有修改任何内核参数。
解决方案
-
比较优雅的方法是使用TCP长连接来代替短连接。
-
HTTP 请求
connection
参数,一般都设置为 `keep-alive,禁止服务端断开 -
缩减
time_wait
时间,设置为1 MSL
(即,2 mins)
问题分析
大量的 TIME_WAIT
状态 TCP 连接存在,其本质原因是什么?
- 大量的短连接 存在
- 特别是 HTTP 请求中,如果
connection
头部取值被设置为close
时,基本都由「服务端 」发起主动关闭连接 - 而,
TCP 四次挥手
关闭连接机制中,为了保证ACK 重发
和丢弃延迟数据
,设置time_wait
为 2 倍的MSL
(报文最大存活时间)
TIME_WAIT 状态:
-
TCP 连接中,主动关闭连接 的一方出现的状态;(收到 FIN 命令,进入 TIME_WAIT 状态,并返回 ACK 命令)
-
保持 2 个
MSL
时间,即,4 分钟
;(MSL 为 2 分钟)