把大图切成小图:每台只存自己那个区域的链路状态。 泛洪量按「区域数的平方」下降,这是分治的收益。
7.5.3 的泛洪量在大网里撑不住,这一节给出解法。 「区域」是 OSPF 最有工程味道的设计,也是它比 RIP 复杂的主因。
一、为什么要切
不划区域的时候,全网是一张图: 每台要存所有路由器的 1 类 LSA,一次变化要在全网泛洪,全网各算一遍 SPF。
| 路由器数 | 每台存几条 | 一次泛洪 | 全网 SPF |
|---|---|---|---|
| 100 | 100 | 9,900 | 100 |
| 500 | 500 | 249,500 | 500 |
| 2000 | 2000 | 3,998,000 | 2000 |
第三列涨得最快:它也是平方级的。 两千台路由器,一次抖动要泛洪四百万次——这不是「慢一点」,是「算不完」。 所以「不分区域的大 OSPF 网」在实践中是不存在的。
二、切成什么样
OSPF 把 AS 切成若干「区域」,其中必须有一个「骨干区域」,编号是 0。 所有其他区域必须直接连到骨干,或者通过一条 virtual link 逻辑上连过去。
| 角色 | 是什么 | 干什么 |
|---|---|---|
| 骨干区域 | 区域 0 | 所有区域间流量都经过它 |
| ABR | 区域边界路由器 | 同时属于两个区域,做汇总 |
| ASBR | 自治系统边界路由器 | 把外部路由引进来 |
「所有区域必须连骨干」这条规矩看着死板,其实是防环的: 区域间的路由只能经过骨干,路径就必然是「上去再下来」的形状,不可能绕成一个圈。 这个约束的代价是「设计不自由」: 如果你的物理拓扑是「三个区域串成一条线」,中间那个区域就没法直连骨干。 这时候要么改拓扑,要么拉 virtual link—— 而 virtual link 本身是很脆的东西(它依赖一条穿过的区域), 所以「能改拓扑就别用 virtual link」是一条经验。
三、切完省了多少
切成 k 个区域,每个区域 n 除 k 台:每台的 LSDB 从 n 条降到「n 除 k 条加几条汇总」。 泛洪范围从「全网」缩到「本区域」。 算一下 500 台切成 5 个区域:每区 100 台,每台存 100 条(原来 500 条)。 一次泛洪 9900 份(原来 249500 份)。 降了 25 倍,正好是 k 的平方。 为什么是「k 的平方」: 因为泛洪量是「区域内的平方」,区域数缩小 k 倍,开方之后就缩小 k 的平方倍。 这就是分治的数学收益——和 7.2.1 说的「把平方变线性」是同一个故事,只是尺度不同。 但「多出来的成本」也要算: ABR 要维护多个区域的 LSDB(内存翻倍),区域间要用 3 类 LSA 汇总(多一层), 而且「跨区域的路由不是最优的」——因为它只按汇总后的度量算,看不见区域内的细节。 所以「区域划得越多越好」是错的,要在「规模」和「最优性」之间找平衡。
四、实践中的区域设计
三条经验:
一、区域别太大。 经验值是一个区域不超过 50 台路由器,有的厂商建议更少。 二、区域边界和地址边界对齐。 这样 3 类 LSA 能做干净汇总,不会误伤。 三、末梢区域(stub)能省就省。 只有一条出口的区域,可以配成 stub,不让外部路由进来,LSDB 更小。
第二条和 7.4.3 的教训是同一件事: 「汇总的边界要和地址规划的边界对齐」—— RIPv1 是被迫汇总,OSPF 是主动汇总,但「对齐」这条要求一样。 所以「地址规划」这件事,跨协议地重要。 第三条值得展开:stub 区域的 ABR 会用一条「默认路由」代替所有外部路由, 区域内的路由器只看到「出去走 ABR」。 这样 LSDB 能小一个数量级——代价是「区域内的路由器不知道外面有几条路,也没法选优」。 对一个「只有一条出口」的分支机构,这个代价等于零,所以 stub 在分支场景里几乎是默认配置。
五、动手 Demo:为什么要划区域
先算单区域的代价,再看 500 台切成 5 个区域之后各项指标怎么变。 重点看那个「二十五分之一」。
def cost(n):
return n, n * (n - 1), n * n
for n in (20, 50, 100, 500):
lsdb, flood, spf = cost(n)
print('%4d 台: LSDB %5d 泛洪 %6d SPF %6d' % (n, lsdb, flood, spf))
print('---- 500 台切成 5 个区域,每区 100 台 ----')
lsdb, flood, spf = cost(100)
print('每台 LSDB %d 泛洪 %d SPF %d' % (lsdb, flood, spf))
print('泛洪降低倍数: %.1f' % (249500.0 / flood))
实跑输出:
--------------------------------------------------------------------
为什么要划区域
--------------------------------------------------------------------
**OSPF 把一个 AS 切成多个「区域」**,**每个区域内部自己泛洪,区域之间只交换汇总信息。**
**这是「分治法」在网络里最直接的一次应用。**
**先看单区域的代价**:
路由器数 每台的 LSDB 条数 一次变化的泛洪 全网 SPF 计算次数
-----------------------------------------------------------------------
20 20 380 400
50 50 2450 2500
100 100 9900 10000
500 500 249500 250000
**100 台路由器,每台要存 100 条链路状态,一次变化要在全网泛洪 9900 份,100 台各算一遍最短路。**
**500 台就是 25 万次 SPF 计算。**
**这不是「慢一点」,是「算不完」。**
**切成 5 个区域,每区 100 台**:
指标 划 5 个区域之后
------------------------------------------------
每台 LSDB 条数 100(原来 500)
一次变化的泛洪范围 9900 份(原来 249500)
参与 SPF 的路由器 100 台(原来 500)
区域间要额外维护 汇总 LSA(每个区域几条)
**泛洪量从 24.95 万降到 9900,是原来的二十五分之一**——
**因为 (n 除 k) 的平方,正好是 n 平方的 k 平方分之一。**
**这就是分治的收益,也是「区域别太大」这条经验的数学来源。**
**分层之后多了两个角色**:
角色 是什么 干什么
---------------------------------------------------------------------------
**骨干区域** **区域 0** **所有其他区域必须连到它**
**ABR** **区域边界路由器** **同时属于两个区域,负责汇总**
**ASBR** **自治系统边界路由器** **把外部路由引进来**
**「所有区域必须连区域 0」这条规矩看着死板,其实是防环的**:
**区域间的路由只能经过骨干,路径就必然是「上去再下来」的形状,不可能绕成一个圈。**
**实在连不上骨干的,才需要拉一条 virtual link 补救。**
泛洪量从 24.95 万降到 9900,是原来的二十五分之一—— 因为 (n 除 k) 的平方,正好是 n 平方的 k 平方分之一。 这就是分治的收益,也是「区域别太大」这条经验的数学来源。 注意「全网 SPF 计算次数」也降了: 从 500 次降到 100 次—— 因为一台路由器只算自己那个区域的树,区域外的目的地它靠 3 类 LSA 拿到「已经算好的结果」, 不再自己算。 这正是 3 类 LSA 的价值:它把「算」这件事分布到各个区域,而不是全网重算一遍。 但 500 台里必然有 5 台是 ABR(每个区域一台连骨干),它们要算两个区域的树, 所以「每台都只算 100 个节点」这句话对 ABR 不成立。 这也说明「ABR 是压力最大的一环」——规划时要给它留余量。
30 秒实验
- 算一下:1000 台切成 10 个区域,泛洪量降到原来的几分之一?
- 想一下:为什么「所有区域必须连骨干」能防环?
- 想一下:stub 区域省了什么,代价是什么?
常见误区
- 以为「区域划得越多越好」。 ABR 内存翻倍、跨区域路不最优,要平衡。
- 以为「跨区域路由和区域内一样优」。 它按汇总度量算,看不见区域内的细节。
- 以为「virtual link 是常规手段」。 它很脆,依赖穿过的区域,能改拓扑就别用。
自测三问(点开对答案)
1. 不划区域的大网会出什么问题? —— **一次抖动要泛洪上百万次**,LSDB 和 SPF 计算也撑不住。 2. ABR 和 ASBR 有什么区别? —— **ABR 连两个区域做汇总**,**ASBR 连外部把外部路由引进来。** 3. stub 区域省了什么? —— **用一条默认路由代替所有外部路由**,LSDB 小一个数量级。下一节跳到 AS 之间,看 BGP 怎么用另一种方式记路径。
- ☐ (本节完,下一节 7.6.1 BGP与AS号)