为什么要有路由这一层
计算机里有句老话:任何问题都能靠加一层 indirection(间接)解决。路由就是这句话在「地址」上的体现——与其让每个使用方直接硬编码最终地址,不如对外只给一个稳定的入口,入口背后真正去哪则集中决定。一旦解耦,「改目标」就和「改入口」分了家:目标随便换,入口纹丝不动。而这一层本身又能拆成两半:一张规则表决定这个入口该去哪(rule),再用某种机制把请求真正送过去(dispatch)——本系列各页讲的,都是这两半的不同组合(匹配引擎是纯粹的 rule;HTTP 重定向、分享入口、deep link 各落地一种 dispatch)。
这一层换来三件事。统一改址:改一处配置,所有渠道、所有已发出的链接同时换目标,海报不用重印、短信不用重发。集中统计:所有流量都过同一个入口,才能在入口处记下来源与访问量,这是各渠道各自硬编码目标时拿不到的数据。安全下线:活动结束时把目标指向一个已下线页即可,而不是留一地指向 404 的死链。
1 · rule 与 dispatch 两半
图 0-1 看着只是「改目标、看入口跟随」,内部却做了两件正交的事:先查规则决定这个入口此刻该去哪(rule),再把请求真正送过去(dispatch)。rule 这一半是全系列共用的决策,匹配引擎把它单独讲透。而 dispatch 这一半有好几种互不相同的机制,不要笼统当成 proxy,proxy 只是其中最具体的一种。
| dispatch 机制 | 谁去请求目标 | 客户端看得见目标 | 本系列对应页 |
|---|---|---|---|
| reverse proxy | 服务端代取目标内容、原样回传 | 看不见,地址栏不变 | 分享入口的 /api/* 反代 |
| redirect(3xx) | 客户端收到 Location 后自己再请求一次 |
看得见,地址栏变成目标 | HTTP 重定向、短链 |
| rewrite | 服务端内部把 path 改写再处理 | 看不见,地址栏不变 | 分享入口的 * fallback |
| OS 层路由 | 操作系统按规则分发,进 App 还是开网页 | 没有地址栏 | deep link |
2 · 硬编码与过一层入口的对照
| 维度 | 各处直接写死最终地址 | 统一过一个路由入口 |
|---|---|---|
| 改目标 | 逐处去改,已印出的改不了 | 改一处配置,全部跟随 |
| 统计 | 各渠道分散、口径不一 | 入口处统一统计 |
| 灰度与 AB | 做不了 | 入口处按比例分流到不同目标 |
| 下线 | 变成一堆死链 | 统一指向「已结束」页 |
| 代价 | 无,但债留给未来 | 多一跳,加一套路由配置要维护 |
这一招无处不在,很多人已经在用而不自知:DNS 把域名指向可变的 IP、CDN 把同一 URL 指向最近的边缘节点、符号链接把路径指向可变的文件、API gateway 把 /v1/* 指向后端可替换的服务。它们解决的是同一个问题——让使用方记住一个不变的名字,而把「它到底指向谁」留给运营方随时调整。短链服务、广告 tracking
link、App 的 deep link 中转乃至 DNS CNAME,设计动机都是同一个。
短链把本页那条 vega.link/promo 单独讲透:它首先解决的是「长 URL 人用不了」的长度问题,indirection 的好处是附带获得的。