分层模型 — 每一层各自决定什么
一句话总结
分层设计要求每层只使用下层服务,并只向上层暴露接口;诊断故障时,它让我们可以问“成功到了哪一层”。
为什么需要它
网络并非由一家公司构建:铺设光纤、制造路由器、开发浏览器的公司各不相同。要在不了解彼此实现的情况下协同工作,就需要边界与契约。分层就是这种契约。下层向上层提供服务,上层无需知道实现细节;TCP 不关心自己的报文段走光纤还是 Wi-Fi。
工作原理
教材中的 OSI 七层与实际互联网的 TCP/IP 模型可对应如下:
| OSI | TCP/IP | 本层决定什么 | 数据单位 |
|---|---|---|---|
| 应用、表示、会话 | 应用 | 交换什么(HTTP、DNS) | 消息 |
| 传输 | 传输 | 发给哪个进程,如何可靠传输 | 报文段 / 数据报 |
| 网络 | 互联网 | 发往哪台主机、走哪条路径 | 数据包 |
| 数据链路 | 链路 | 如何到达同一网络的下一设备 | 帧 |
| 物理 | 链路 | 如何把比特变成信号 | 比特 |
封装是在上层数据外添加下层首部。HTTP 请求加 TCP 首部成为报文段,加 IP 首部成为数据包,再加以太网首部成为帧;接收方按相反顺序拆除。
需要避免一个常见误解:OSI 七层是教学模型,不是互联网实现。 互联网没有与表示层、会话层精确对应的协议,因此“TLS 属于第几层”没有唯一答案。TLS 运行在 TCP 之上并加密应用数据,放在哪层都不完全贴切。模型用于帮助理解,并非实体。
实际工作中的表现
分层模型的实用价值在诊断顺序。无法连接时依次询问:
- 名称能否解析——
getent hosts api.example.com(应用层之下的名称解析) - 能否与该地址建立 TCP 连接——
curl -v --connect-timeout 3 http://주소:포트/ - 连接成功却没有响应吗——说明传输层已通过,问题在应用层
这样可把“网络坏了”改成“停在第 3 步”。即使练习环境不能使用 ping 或 tcpdump,仅用 ss、curl、dig、getent、/proc/net/* 也能检查全部三步。
按症状定位层次
分层模型的实践价值是根据症状决定查看哪一层。
| 症状 | 可疑层 | 检查命令 |
|---|---|---|
| 链路未启用 | L1 物理 | ip link、线缆、SFP |
| 同一子网不通 | L2 | ip neigh、ARP 响应 |
| 其他网段不通 | L3 | ip route get、traceroute |
| 只有端口不通 | L4 | nc -zv、防火墙 |
| 名称无法解析 | 应用(DNS) | getent hosts、dig |
| TLS 错误 | 表示(TLS) | openssl s_client -connect |
| 404、500 | 应用 | 应用日志 |
原则上应自下而上,但实践中从中间层(L3/L4)开始通常更快,因为物理故障较少,应用问题又有日志可查。
封装带来的开销
每层都增加首部,实际数据空间因此减少。
이더넷 프레임 1518 바이트 (MTU 1500)
− IP 헤더 20
− TCP 헤더 20
= 1460 바이트가 실제 데이터 (MSS)
VPN 或覆盖网络还会增加首部。VXLAN 额外使用 50 字节,使实际 MSS 变为 1410。MTU 不匹配会使大数据包被分片或丢弃。
这也是 Kubernetes 中“小请求正常,大响应卡住”的一个原因。路径 MTU 发现(PMTUD)使用 ICMP;若防火墙阻断 ICMP,发送方会持续发送过大的数据包却收不到响应,形成 PMTU 黑洞。
# 조각내지 않고 보낼 수 있는 최대 크기 찾기
ping -M do -s 1472 <대상> # 1472 + 28(ICMP+IP) = 1500
为什么区分 TCP 与 UDP
| TCP | UDP | |
|---|---|---|
| 连接 | 3-way 握手 | 无 |
| 顺序、重传 | 保证 | 无(由应用处理) |
| 流量控制 | 有 | 无 |
| 到首字节时间 | 至少多 1 RTT | 立即 |
DNS 使用 UDP 的原因是为一次查询进行握手很浪费。响应超过 512 字节时会改用 TCP 重试。
QUIC 在 UDP 之上重新实现可靠性与加密,在避免 TCP 的问题(队头阻塞、实现固化在内核)的同时获得可靠传输。
后续测验将确认什么
确认你理解每一层决定什么、封装顺序如何,以及 OSI 模型应相信到什么程度。