📚 第五章 IP协议相关技术
📄 一句话概括

任播是「一个地址配在多台机器上,路由把包送到最近的那台」:地址相同,位置不同。 DNS 根服务器就是这么干的:13 个地址、上千个实例,换机器不用改任何配置。

📝 本节和前面几节的关系

5.8.1 的多播是「一组里全都要」,任播是「一组里只要一台」,方向正好相反。 4.4.1 讲的路由控制是它的地基,任播完全靠路由表选「最近」。

一、四种通信方式摆一起

这四个词的区别只有两点:配在几台上、收到的是谁

类型 配在几台上 实际收到的是
单播 一台 唯一
广播 同网段全部 全都要收
多播 一组 订阅了的全部
任播 一组 最近的一台

第四行最容易和第三行混:多播是「发给一组,组里所有人都收到」; 任播是「一组人共用一个名字,但每次只有一个人接电话」。 换句话说:多播是「广播找人」,任播是「总机转接」。 任播不需要任何新协议:它就是「同一个地址配在多处,让路由协议自己去选」。 所以它是个「用路由实现的服务分发」,不是一种新的传输方式。

二、根服务器为什么需要它

DNS 根服务器只有 13 个地址(a 到 m),但全世界实际有上千个实例在跑。 它们共用那 13 个地址,靠 BGP 各自宣告「我这儿也有这个地址」。 为什么要限制成 13 个:早期 DNS 的响应包要装进 512 字节的 UDP 里, 13 个地址的列表正好塞得下,再多就放不进去了。 所以这个数字是「协议约束」的结果,不是「设计者觉得 13 好」。 把上千个实例塞进 13 个地址,好处立刻出来:查询会被路由带到「离你最近」的那台, 而客户端完全不知道、也不需要知道自己是连到了哪台。

三、三个好处

第一是就近:路由表本来就选「最短路径」,所以任播等于「免费拿到了一个全局负载均衡」。 不需要 DNS 轮询,不需要 GSLB,不需要在客户端装任何东西。 第二是抗攻击:攻击流量会被路由分散到各个实例上,而不是全砸在一台上。 这里要说清一个常见的误解:任播并不能「让攻击消失」,它只是「把压力摊开」, 被集中的那一个实例照样会被打垮。 第三是能搬:换机房、换 IP,只要把 BGP 宣告撤掉再在新地方宣告, 客户端配置一个字都不用改。 这一点对「根服务器」这种「配置写死在全世界几百万台设备里」的东西,价值极大。

四、代价:排障变难,会话会漂

第一个代价是「同一个地址在不同地方连到不同的机器」: 所以「我这里能通、你那里不通」是正常现象,不能简单归因为「服务器挂了」。 做全球服务时,这一点经常让人困惑半天。 第二个代价更硬:路由一变,后续的包可能送到另一台机器上。 对于「一问一答」的 DNS,这没关系——一个查询一个响应,完事就结束。 但对于「长时间保持的 TCP 连接」,这就是灾难: 新机器上没有这条连接的上下文,只能回一个 RST。 所以任播适合「无状态、短交互」的服务(DNS、NTP、CDN 的入口), 不适合「有状态、长连接」的服务, 除非后端把状态共享出去—— 这就是为什么有些任播服务「看起来只是一个地址」,背后其实是一整套同步机制。

五、动手 Demo:任播,一个地址很多台机器

算一下 13 个根地址平摊到 1000 个实例,一个地址对应几个节点。 再看单播、多播、任播三者的差别。

roots, inst = 13, 1000
print('%d 个地址,约 %d 个实例,平均一个地址 %d 个节点'
      % (roots, inst, inst // roots))

实跑输出:

--------------------------------------------------------------------
任播,一个地址很多台机器
--------------------------------------------------------------------
**任播是「同一个地址配在多台机器上,路由负责送到最近的那台」。**
**它和多播的区别是「只要一台」,和单播的区别是「可以是很多台里的任意一台」。**

  类型         配在几台上     实际收到的是
  -------------------------------------------
  **单播**     **一台**       **唯一**
  **多播**     **一组**       **全部**
  **任播**     **一组**       **最近的一台**

**最著名的例子是 DNS 根服务器**:**全球只有 13 个根地址(a 到 m),但实际有上千个实例。**
**它们共用那 13 个地址,靠 BGP 宣告「我这儿也有」。**

**算一下这个设计的好处**:
**13 个地址、约 1000 个实例,平均一个地址 76 个节点。**
**好处有两个**:**一是「就近响应」**(路由自动选近的);
**二是「抗攻击」**(打掉一个还有别的,而且换 IP 都不用改根配置)。**

**代价是「排障变难」**:**同一个地址在不同地方连到不同的机器**,
**所以「我这里能通、你那里不通」是正常现象**,**不能简单归因为「服务器挂了」。**
**这一点在做全球服务时经常让人困惑。**

76 这个数说明「一个根地址背后是一群机器」: 有人以为「根服务器只有 13 台」,其实「地址只有 13 个,机器有上千台」。 这个误会很常见,也很要命——因为它会让人以为「打掉一台就断半个互联网」。 「平均 76 个」也说明了任播的另一个特性: 你有多少实例,取决于「你在多少个地方宣告了这个地址」,而不是「协议允许几个」。 所以扩容任播服务,本质上就是「在更多机房宣告同一个前缀」。 最后一句提醒:任播的「最近」是按路由跳数算的,不是按地理距离: 所以「离你最近的那台」有时候会绕远——这是「任播性能不符合直觉」的主要原因。

30 秒实验

  1. 想一下:任播和多播,收到的分别是「全部」还是「一台」?
  2. 算一下:2000 个实例共用 13 个地址,平均一个地址几个节点?
  3. 想一下:为什么长连接的 TCP 服务不适合直接上任播?

常见误区

  1. 以为「根服务器只有 13 台机器」。 是 13 个地址、上千个实例,靠任播共用一个地址。
  2. 以为「任播能挡住攻击」。 它只是把流量摊开,被集中的那个实例照样会垮。
  3. 以为「任播靠地理距离选最近」。 它靠路由度量,所以偶尔会绕远。
自测三问(点开对答案) 1. 任播和多播的本质区别? —— **多播是一组里所有人都收到,任播是一组里只有最近的一台收到。** 2. 为什么根服务器地址只有 13 个? —— **早期 DNS 响应要装进 512 字节 UDP**,13 个地址的列表正好放得下。 3. 任播为什么不适合长连接? —— **路由一变,后续的包会到另一台机器**,那台没有连接上下文,只能 RST。

下一节讲「带宽不够的时候,谁先走」:通信质量控制。

相关笔记