深浅色
计算机网络(背诵版)
1. TCP 三次握手 / 四次挥手
- 三次:SYN(seq=x) -> SYN+ACK(seq=y, ack=x+1) -> ACK。
- 为什么不能两次:服务端无法确认客户端的接收能力;且网络中滞留的旧 SYN 可能让服务端白白建立连接。
- 四次挥手:FIN -> ACK -> FIN -> ACK。因为 TCP 全双工,一方关闭后另一方可能还有数据要发,ACK 和 FIN 不能合并。
- 追问:为什么 TIME_WAIT 要等 2MSL?-> 保证最后的 ACK 能到达(否则对端重传 FIN),并让旧报文在网络中消散。
2. TIME_WAIT 过多
- 只有主动关闭方会进 TIME_WAIT,Linux 默认 60 秒。
- 过多的原因:短连接太多、服务端主动关闭连接。
- 优化:用连接池复用连接、让客户端主动关闭、谨慎开 tcp_tw_reuse。
- 追问:TIME_WAIT 的危害?-> 耗尽本地端口,导致无法建新连接。
3. 拥塞控制
- 四阶段:慢启动(指数增长到 ssthresh)-> 拥塞避免(线性增长)-> 快速重传(3 个重复 ACK)-> 快速恢复。
- CUBIC:用三次函数增长,适合高带宽长距离。
- BBR:基于带宽和 RTT 建模,不把丢包当拥塞信号。
- 追问:BBR 在什么场景优势明显?-> 有一定丢包率的长肥链路。
4. 粘包与拆包
- TCP 是字节流,没有消息边界,所以会粘包(多个小包合并)和拆包(大包被切开)。
- 解决:长度前缀(最常用)、固定长度、特殊分隔符。
- 追问:UDP 有粘包吗?-> 没有,UDP 保留消息边界。
5. keep-alive 与连接池
- HTTP keep-alive 复用 TCP 连接,省掉握手开销。
- Go 的 http.Client 默认复用连接,但要调
MaxIdleConnsPerHost(默认只有 2,高并发下太小)和 IdleConnTimeout。 - 必须读完并关闭 response body,否则连接不会归还池子。
- 追问:body 没读完为什么连接不能复用?-> 残留数据会污染下一个请求。
6. DNS 与 CDN
- 解析顺序:浏览器缓存 -> 系统缓存 / hosts -> 本地 DNS -> 根 -> 顶级 -> 权威。
- CDN 用 CNAME 把域名指向 CDN,再由 GSLB 按用户 IP 就近返回边缘节点。
- 追问:DNS 用 TCP 还是 UDP?-> 一般 UDP 53;响应超过 512 字节或区域传送用 TCP。
7. gRPC
- 基于 HTTP/2:多路复用、头部压缩,支持一元 / 服务端流 / 客户端流 / 双向流四种模式。
- Protobuf 二进制编码,比 JSON 更小更快,强类型且能生成代码。
- 追问:gRPC 和 REST 怎么选?-> 内部服务间用 gRPC(性能 + 契约);对外开放用 REST/JSON。
8. 负载均衡
- L4:基于 IP + 端口转发,性能高但看不到内容。
- L7:基于 HTTP 内容路由(路径、header、cookie),能做灰度、限流、鉴权。
- 算法:轮询、加权轮询、最少连接、一致性哈希。
- 追问:长连接下轮询为什么不均衡?-> 连接建立后不再重分配,负载会倾斜,要用最少连接或一致性哈希。