为什么打开 TCP 套接字开销大:握手、状态与系统成本

副标题 / 摘要 TCP 连接不是一次函数调用,而是一组协议状态机与内核资源分配。本文解释开销来源,并给出工程上的优化路径。 目标读者 负责网络服务优化的后端工程师 想理解连接成本的系统开发者 需要排查连接耗时的运维与 SRE 背景 / 动机 在高并发系统里,“频繁建连”常常成为性能瓶颈。 理解 TCP 连接开销来源,才能知道何时该用连接池、何时该复用、何时该改协议。 核心概念 三次握手:SYN/SYN-ACK/ACK 内核状态:连接表、套接字缓冲区、TCP 状态机 慢启动:初始窗口小、吞吐从低到高 系统调用成本:socket/connect/accept 带来上下文切换 实践指南 / 步骤 优先复用连接(HTTP keep-alive / 连接池) 减少短连接,批量或长连接替代 降低握手成本(TLS session resumption) 调优内核参数(连接队列、端口范围) 监控连接层指标(SYN 重传、TIME_WAIT) 可运行示例 下面脚本在本机测量多次建连成本: import socket import threading import time def server(port_holder, ready, n): s = socket.socket() s.bind(("127.0.0.1", 0)) port_holder.append(s.getsockname()[1]) s.listen() ready.set() for _ in range(n): conn, _ = s.accept() conn.close() s.close() def measure(n=200): port_holder = [] ready = threading.Event() t = threading.Thread(target=server, args=(port_holder, ready, n), daemon=True) t.start() ready.wait() port = port_holder[0] start = time.perf_counter() for _ in range(n): c = socket.create_connection(("127.0.0.1", port)) c.close() elapsed = time.perf_counter() - start print(f"{n} connections: {elapsed:.3f}s") if __name__ == "__main__": measure() 解释与原理 TCP 连接要维护状态机、缓冲区、窗口、重传计时器。 每次建连都需要三次握手与内核资源分配,还会触发慢启动,吞吐无法立即拉满。 ...

2026年1月24日 · 1 分钟 · map[name:Jeanphilo]

TCP 与 HTTP 的区别:分层、语义与选型

副标题 / 摘要 TCP 是传输层协议,HTTP 是应用层协议。二者的职责与语义完全不同,但经常被混淆。本文用工程视角梳理差异与选型。 目标读者 需要排查网络问题的后端工程师 想理解协议分层的开发者 Web 服务与客户端开发人员 背景 / 动机 很多线上问题都源于“层次混淆”:把 HTTP 的问题当 TCP 处理,或把 TCP 的问题当 HTTP 处理。 理解分层,是定位问题与做技术选型的基础。 核心概念 TCP:可靠、面向连接的字节流传输 HTTP:在传输层之上定义请求/响应语义 分层模型:传输层解决“怎么送到”,应用层解决“送什么” 实践指南 / 步骤 先看连接层:是否能建立 TCP 连接(握手、丢包、重传) 再看应用层:请求是否符合 HTTP 协议(方法、头、状态码) 分层排查:TCP 通了但 HTTP 失败,多半是应用层问题 选型时分清职责:HTTP 可以跑在 TCP 或 QUIC 上 常用诊断命令: # 看 TCP 连接建立 nc -vz host 80 # 看 HTTP 层返回 curl -v http://host/ 可运行示例 先在本机启动一个 HTTP 服务: python3 -m http.server 8000 再用 socket 直接发 HTTP 请求: ...

2026年1月24日 · 1 分钟 · map[name:Jeanphilo]