tcp 二次握手时延_记一次TCP性能问题

在程序性能测试中发现一个POST请求处理耗时100ms,通过Wireshark分析发现是TCP慢启动导致的。文章介绍了TCP慢启动原理,并提出两种解决方案:使用长连接或调整TCP初始窗口大小和缓冲区尺寸。同时提醒注意TCP在高延迟环境下的性能问题。

网络工程师通常更多注物理层/数据链路/IP层的性能和可达性,而开发工程师则更加关注应用层/服务器的性能,在中间的TCP层的性能和问题容易被忽视。最近在做程序性能测试时发现一个POST请求异常的花了100+ms的时间。本文记录了debug过程和一些tcp的相关内容。

为了简化说明这个问题,我们可以将问题抽象如下:

1) 有一个HTTP服务器,提供一个处理POST请求的Handler,这个请求里面,可以简化认为什么都不做,只是读取客户端的Request Body就直接返回了。
2) HTTP客户端发送了一个POST请求, Body大概是500KB左右。
3) 客户端和服务器处在两个数据中心,它们之间的时延大概在20ms左右。

1c3f85065db20f0ea542f7c2c02031c6.png

但问题是:明明在Handler里面除了打印一下body什么也没做,为什么Handler却花了100ms左右。

那这100ms究竟花在了哪里呢?Wireshark抓包看一下:

09c95911e1f4fd74df74829f1e63e1c5.png

10.0.0.83 是客户端IP,10.0.4.166是服务器端IP。可以发现每隔一段时间(红色部分),发送端会出现一次0.02s左右的时延。一共出现了5次,因此有了100+ms的时延。

下图是TC

### RTT时延TCP三次握手时延劣化的可能原因及影响因素 #### 一、RTT时延劣化的影响因素 RTT(Round Trip Time)是指数据包从发送端到接收端再返回所需的时间。以下是可能导致RTT时延劣化的主要因素: 1. **网络路径上的物理距离** 数据在网络中的传播速度受到光速的限制,因此地理距离越远,RTT通常会越大[^2]。 2. **路由器和交换机的处理能力** 如果中间节点设备性能不足或负载过高,可能会导致数据包排队等待时间增加,从而延长RTT[^2]。 3. **链路质量与带宽瓶颈** 带宽较低或者存在丢包现象的链路会影响数据传输效率,进而增大RTT。此外,拥塞控制机制也可能因感知到网络拥堵而人为降低速率[^2]。 4. **DNS解析延迟** 在发起TCP连接之前,域名需被解析成IP地址。如果DNS服务器响应缓慢,则整个流程会被推迟,间接增加了整体RTT[^5]。 5. **防火墙或其他安全措施** 安全设备如防火墙、入侵检测系统等对流量进行扫描检查也会消耗额外时间,造成RTT上升[^5]。 --- #### 二、TCP三次握手时延劣化的影响因素 TCP三次握手中涉及多个阶段的操作,任何环节出现问题都会引起时延恶化。具体来说有以下几个方面: 1. **初始SYN报文丢失或重传** 当客户端发出的第一个SYN请求未能成功到达服务端时,需要按照指数退避算法重新尝试发送,这无疑拉长了建连耗时[^1]。 2. **服务端Accept队列满载** 若大量并发请求涌入使得accpet队列溢出,则后续新来的连接不得不等待已有连接被接受并释放空间才能继续执行下一步操作,这种情况可通过调整backlog参数缓解[^3]。 3. **操作系统内核配置不当** 错误设置某些关键参数比如somaxconn、tcp_max_syn_backlog等同样会造成三步握手失败率升高以及相应时间变长等问题。 4. **ACK确认滞后** 即使双方已经完成了前两轮交互,在最后一个由客户方向服务器反馈同意建立链接的消息里若出现异常状况比如说超时未回应等情况依旧会导致总历时加长[^1]。 5. **MTU不匹配引发分片重组开销** 不同网段间可能存在最大传输单元(MTU)差异,当超过规定尺寸的数据帧穿越边界时就必须拆分成更小单位后再逐一传递回来组装好原貌;这一过程必然耗费更多资源同时也拖慢进度[^5]。 6. **加密协商带来的附加负担** 对于HTTPS这类采用SSL/TLS保护的应用场景而言,除了标准意义上的三个回合外还需要额外花费精力用于密钥交换等工作,所以总体表现出来的效果便是更加明显的迟滞感[^5]。 --- ```python import socket from time import perf_counter def measure_rtt(host='www.example.com', port=80, num_pings=5): rtt_list = [] for _ in range(num_pings): try: start_time = perf_counter() with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.settimeout(5) s.connect((host, port)) end_time = perf_counter() elapsed_ms = (end_time - start_time) * 1000 rtt_list.append(elapsed_ms) except Exception as e: print(f"Ping failed: {e}") avg_rtt = sum(rtt_list)/len(rtt_list) if rtt_list else float('inf') return avg_rtt, rtt_list avg_rtt, all_rtts = measure_rtt() print(f"Average RTT to server is {avg_rtt:.2f} ms.") if all_rtts: print("Individual measurements:", ", ".join(map(lambda x:f"{x:.2f}",all_rtts))) else: print("No successful pings recorded.") ``` --- ####
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值