本文是《从 IP 到 SRv6 计算编排》新手教材第 6/13 编。 总目录 · 上一篇:第五编:算子让网络路径执行计算 · 下一篇:第七编:SPP、图像 Tile 与部分成功
前五编已经建立普通IPv6 FIB、逻辑/具体SID、任务和算子实例。本编才第一次系统学习服务 选择:先从普通路由理解“多个实例共享一个逻辑地址”,再观察provider怎样自然变化。第七编 随后加入跨包状态,说明漂移的代价;第九编最后学习更复杂的全链联合选择。这样不会用尚未 定义的图片窗口或调度公式反过来解释Anycast。
40. 先从Unicast、Multicast和Anycast的区别开始
学习Anycast以前先比较三种交付方式:
| 方式 | 中文 | 一个包交给谁 |
|---|---|---|
| Unicast | 单播 | 一个明确地址对应的一个目的 |
| Multicast | 组播 | 加入同一组的一组接收者 |
| Anycast | 任播 | 多个实例共享一个地址,路由选择其中一个 |
Anycast不会把同一个包复制给所有provider。它仍是一条普通IPv6 /128路由,只是多个
位置都能提供这个逻辑目的。哪一个实例收到包,由当前节点的FIB和下一跳决定。
41. 为什么计算服务需要逻辑地址
第五编已经区分operator type(算子类型)与operator instance(算子实例)。若调用者写:
fd42:3:14::100
它明确要求node-20上的Gray,节点20不可达时这个地址不会自动变成node-38。若调用者只要求 “某个可达Gray”,则使用逻辑服务SID:
fd42:7::100
因此:
具体SID = 功能 + 物理实例位置
逻辑Anycast SID = 只有功能身份,位置交给路由选择
当前节点本地Anycast FIB覆盖五种图像服务:BNN Fire Filter、Gray、Tile Mean 2×2、 Tile Blur 3×3和Edge。Fire Mask与Binary Fire Mask仍有具体实例能力,但不属于当前 Issue 243逻辑Anycast图像链,不能仅凭“统一镜像里有七类算子”就虚构其Anycast route。
42. Provider事实从哪里来
**Provider(提供者)**是当前真实运行某个算子实例的网络节点。节点启动自己的算子以后, 把operator bitmap、进程instance、resource sequence和lifetime作为事实上报。控制器只 汇总这些节点事实,再把同一份资源视图传播给网络节点。
每个节点本地计算Anycast路由时只使用自己已经接收并应用的:
confirmed topology graph
+ operator provider bitmap
+ 本地HELLO观察到的直接邻居可用性
配置文件声称某节点“应该有Gray”不等于该实例当前可用;事实过期、进程重启或节点不可达 都必须自然改变候选集。控制器不进入容器探测,也不替节点选provider。
43. 每个节点怎样计算Primary和Backup
scripts/anycast_fib.py从观察节点对当前双向图执行BFS,为每个provider寻找经不同本地
first hop可达的确定性路径。候选按以下规则排序:
- primary先选hop数最少者;
- hop数相同按provider node ID和完整path稳定排序;
- backup必须来自另一个provider;
- 有条件时优先选择与primary不同的first hop;
- 其余provider继续保留为有序候选。
“不同provider”避免把同一实例的另一条等价路径误称为实例冗余;“尽量不同first hop”让 直接邻居故障时更可能立即切换。它是一条通用、确定性的路由规则,不读取当前有哪些task, 更不按某次业务结果安排答案。
44. 逻辑服务怎样安装进Linux FIB
每个逻辑service SID都有稳定的Linux nexthop object和一条普通IPv6 /128路由。初始化时
nexthop先指向blackhole(黑洞),表示尚无合法provider;节点得到事实后用一次iproute2
batch替换对应nexthop:
远端provider:via fe80::<next-hop> dev 数据接口
本地provider:via 算子namespace网关 dev 本地算子veth
无provider:blackhole
路由本身保持稳定,活动nexthop对象改变。直接HELLO发现primary first hop down时,节点可 从预计算候选中立即选择backup,不等待控制器生成一份“正确答案”;之后的新全局拓扑再重建 完整候选集。
45. Resilient任务怎样使用Anycast
**Resilient Placement(弹性放置)**把DAG中的算子类型编译成逻辑SID链。例如:
逻辑Gray SID → 逻辑Mean SID → 逻辑Edge SID → 最终交付SID
入口安装task SR Policy时不运行HEFT,也不选择node-20或node-38。包到达某个逻辑SID时, 该位置的普通IPv6 FIB选择当前provider。拓扑或实例变化只替换逻辑服务nexthop,task_id、 Color和SRH服务顺序保持稳定。
这就是routing-based placement(基于路由的放置):每项服务在到达时做局部路由选择。 它与第九编的HEFT全链联合编排是两种不同模型,不能因为最终都得到某个provider,就把 Resilient选择称为HEFT结果。
46. Provider漂移为什么是自然现象
假设node-17当前到Gray的排序为:
primary = Gray@20, first hop 18
backup = Gray@38, first hop 44
当17实际收不到18的HELLO/ACK,或Gray@20事实过期,FIB自然改选Gray@38。已经发出的旧包 可能到20,新包到38;没有任何组件把一个包复制给两个容器。
这种变化叫Provider Drift(提供者漂移)。对单包无状态算子,两个合规实例给出相同 算法结果,漂移通常只造成路径变化。对需要跨包缓存的有状态算子,不同包落到不同实例会 拆散窗口。第七编在定义SPP对象和Tile以后再精确解释这种损失,当前只保留因果链:
拓扑/实例事实变化 → 各节点本地FIB变化 → 后续包选择变化
47. Anycast应该记录和展示哪些事实
节点对每个逻辑服务记录:
anycast_route_selected:从无路由变成选中provider;anycast_route_changed:活动provider或first hop变化;anycast_route_withdrawn:没有合法provider;anycast_candidates_changed:活动转发身份未变,但主provider/下一跳或备 provider/下一跳发生变化;- service SID、operator、primary、backup、candidate count和topology generation;
- 受影响Resilient task的稳定nexthop是否重新绑定。
第三顺位以后的候选路径仍由每个节点持续计算,并保存在latest-only状态中。它们没有 改变当前内核FIB,也没有改变立即可用的主备转发前沿,因此不为每次路径重算写一条永久 事件。减少的是可重建的派生转录,不是资源、拓扑、故障或业务事实。
前端只能把这些真实FIB事件画成Anycast漂移,不能根据两颗卫星在画面上的距离猜provider。 排错时先问“该观察节点当时有哪些已应用provider事实和路径”,不能从目的端结果倒推出一条 人为粘性规则。
47.1 第六编自测
- Anycast与Multicast的核心差别是什么?
fd42:3:14::100和fd42:7::100分别表达什么?- 为什么每个节点会算出自己的Anycast FIB,而不是控制器下发一个全网provider?
- backup为什么要求另一个provider并尽量使用不同first hop?
- provider变化为什么不需要替换Resilient task的SRH?
- 同一个包会不会因为Anycast被复制给五个容器?