跳转至

02 网络与通信

难度:入门到中级|前置:系统思维|目标:理解连接、请求、超时和重试

从一次请求开始

应用调用另一个服务,并不是直接执行对方函数:

应用
→ DNS 找地址
→ 建立 TCP 连接
→ 可选 TLS 握手
→ 发送 HTTP/MQTT 数据
→ 对方排队和处理
→ 返回数据

每一段都可能超时或失败,因此“请求没收到响应”不等于“对方没有执行”。

TCP 提供什么

TCP 提供同一连接内的:

  • 有序字节流;
  • 丢包重传;
  • 流量控制;
  • 拥塞控制。

TCP 不提供:

  • 业务消息边界;
  • 对方业务是否成功;
  • 请求是否只执行一次;
  • 跨连接的业务顺序;
  • 永不掉线的保证。

这就是为什么应用层仍需要消息 ID、确认、幂等和状态机。

短连接与长连接

HTTP 请求

现代 HTTP 通常会复用连接,但业务模型仍然是一问一答。适合 API、查询和普通操作。

WebSocket

在一个长连接上双向发送消息,适合浏览器实时状态、流式音频和 Agent 流式事件。

MQTT

面向发布/订阅和不稳定设备网络,Broker 负责 Topic 路由、会话和 QoS。

长连接不是免费资源。需要维护:

  • socket;
  • 文件描述符;
  • 连接状态;
  • 心跳;
  • 发送缓冲;
  • 订阅关系;
  • 断线恢复。

超时要分层

“设置一个 30 秒超时”通常不够。需要区分:

超时 含义
连接超时 多久连不上就放弃
读取超时 多久收不到响应
写入超时 多久发不出去
请求总超时 整个业务允许多久
空闲超时 连接多久无活动后关闭
任务超时 异步任务最长运行多久

重试为什么危险

请求超时可能有两种情况:

A. 对方没有收到
B. 对方成功执行,但响应丢了

客户端无法仅凭超时区分 A 和 B。对有副作用的操作重试前,必须设计幂等键。

背压

如果每秒收到 5,000 条消息,下游只能处理 3,000 条:

积压每秒增加 2,000

缓存再大也只是延迟问题暴露。背压策略包括:

  • 限制生产速度;
  • 限制并发;
  • 批处理;
  • 丢弃可丢数据;
  • 降级;
  • 扩容消费者;
  • 对积压告警。

自测

  1. TCP 已经可靠,为什么业务仍然可能重复?
  2. HTTP 超时后为什么不能直接认定操作失败?
  3. MQTT 长连接需要消耗哪些资源?
  4. 队列越来越长时,为什么加内存不是根治?

完成标准

  • 能画出一次 HTTPS 请求的主要阶段
  • 能解释 TCP 保证什么、不保证什么
  • 能区分至少四种超时
  • 能解释重试为什么必须配合幂等

下一单元:并发与异步