前面篇章把 Listener → HCM → Router → Cluster 与 xDS / Hot restart 钉成内核。生产里下一问通常是:鉴权、限流、自定义逻辑该进原生 filter、Lua、Wasm,还是外部服务? 答错的代价不是「多写几行配置」,而是把延迟、故障域和安全边界画歪。
本文只标机制位置与边界,不写 Wasm SDK、Lua 手册或限流服务搭建教程。沙箱与 WASI 通则见 architecture/97;令牌桶/过载算法见 architecture/25。可观测如何挂上这些扩展,见 第 14 篇。
本文是「Envoy / 数据面代理内核」系列第 13 篇(共 16 篇)。→ 系列目录
篇目 核心内容 第 12 篇 · Hot restart / drain 进程级变更 第 13 篇 · 扩展边界 Wasm / Lua / ext_authz / ratelimit 第 14 篇 · 可观测数据面 stats / log / tracing 落点
版本锚定:Envoy v1.39.0 HTTP Wasm / Lua / External Authorization / Local rate limit / Rate limit 过滤器文档。Wasm filter 在该版本仍标为 experimental。
一、先画格子:扩展插在哪
Envoy 扩展按事件模型落在不同层(与 第 1 篇 请求路径轴一致):
| 层 | 事件 | 本篇代表 |
|---|---|---|
| Network filter | 连接字节流 | 较少用 Lua/Wasm 做主鉴权;L4 策略另论 |
| HTTP filter 链 | 已解码的请求/响应 | Lua、Wasm、ext_authz、local/global ratelimit |
| Router 之后 / 上游 | 选 cluster 之后 | Upstream Wasm 等(仍属 HTTP 上游路径) |
| 进程外 | gRPC/HTTP 调用 | ext_authz、global rate limit 服务 |
flowchart LR
subgraph hcm ["HCM HTTP filter chain"]
Lua["Lua"]
Wasm["Wasm"]
Authz["ext_authz"]
LRL["local_ratelimit"]
GRL["ratelimit filter"]
Router["Router"]
end
Authz -->|"CheckRequest"| ExtSvc["External authz service"]
GRL -->|"ShouldRateLimit"| RLSvc["Rate limit service"]
hcm --> Upstream["Upstream cluster"]
顺序语义(第 6 篇展开):先匹配的 filter 先看到请求。鉴权放在可能改路由的过滤器之后,会引入「先定路由再鉴权 / 清 route cache 后绕过鉴权」类问题——v1.39.0 ext_authz 文档对此有专节警告。
二、Wasm:隔离与 ABI,不是「万能插件槽」
2.1 在 Envoy 里的位置
envoy.filters.http.wasm(及网络/上游变体)把用户模块跑在
Wasm VM 中,经 Proxy-Wasm 风格宿主 ABI 访问
headers、body、metadata。配置形如本地 .wasm
或远程加载(具体字段见 v1.39.0 Wasm filter
文档)。Windows 不支持;文档标明
experimental,配置结构仍可能演进。
2.2 与 architecture/97 的分工
| architecture/97 | 本篇 |
|---|---|
| Core 语义、WASI、组件模型、Isolate 对照 | Envoy embedder 边界:filter 链位置、实验状态、与原生 C++ filter 的权衡 |
| 通用插件架构 | 不教如何写 filter 代码 |
谱系回指:Wasm 的沙箱假设来自 Haas et al., PLDI 2017
等(详见 97);Envoy
选用它,是为在代理进程内跑不可全信逻辑,同时比直接
dlopen 原生插件少一层内存破坏面。代价是:ABI
稳定性、序列化/拷贝、VM
实例生命周期,以及实验特性的运维不确定性。
2.3 何时不该用 Wasm
- 需要稳定、极低延迟的热点路径 → 优先成熟原生 filter。
- 需要完整系统调用面或任意 ELF → 容器/旁路服务,而不是 Proxy-Wasm。
- 只是改几个 header → Lua 或原生 formatter 往往更简单(见下节权衡)。
三、Lua:同进程脚本,边界在「信任与安全交互」
Lua HTTP filter 在 Worker 内解释执行,能读改 headers、与异步集群调用等(能力以 v1.39.0 Lua 文档为准)。机制特征:
- 无 Wasm 级沙箱:脚本与 Envoy 同信任域;适合运维可控的粘合逻辑,不适合多租户不可信代码。
- 与 filter
链强耦合:
clearRouteCache()等 API 会改变后续匹配——若放在 ext_authz 之后,可能造成「鉴权按旧路由、转发按新路由」或绕过鉴权。官方 Filter route mutation security considerations 与 ext_authz 专节把此列为 privilege escalation 风险。 - 性能:解释执行 + 每请求进入;复杂逻辑或高 QPS 时通常不如原生/精心编写的 Wasm,但本篇不给未测数字。
一句话:Lua 是可信运维的手术刀,不是租户插件平台。
四、ext_authz:把决策挪出数据面
External Authorization filter 在请求路径上调用外部 gRPC
或 HTTP 服务,用 CheckRequest / 响应决定放行或
403(可配置)。机制要点:
| 维度 | 含义 |
|---|---|
| 失败域 | 鉴权服务超时/错误 → 由 failure_mode_allow
等决定 fail-open / fail-closed |
| 数据面负担 | 每请求(或按 runtime 采样)一次出站调用;可带
body(with_request_body) |
| 安全耦合 | 必须注意与后续清 route cache 的 filter
的顺序;推荐用 ExtensionWithMatcher
做条件启用,而非仅依赖已 disabled 的 filter
上的 metadata 开关 |
| 可观测 | ok / denied /
error / failure_mode_allowed 等
cluster 命名空间计数 |
与 Wasm/Lua 的对比:策略实现与发布可独立于 Envoy 二进制,但换来同步依赖:鉴权集群与数据面同命运。Mesh 里常见「策略中心 + ext_authz」,属于产品层选择;本系列只要求读者能指出过滤器挂点和失败语义。
五、Local vs Global rate limit:算法在 25,落点在 filter
architecture/25 讲令牌桶、滑动窗口、过载保护的算法与部署层。Envoy 侧对应两个机制位置:
5.1 Local rate limit
- Filter:
envoy.filters.http.local_ratelimit。 - 令牌桶在 Envoy 进程内(默认同进程多 worker 共享;可改为 per-downstream-connection)。
- 超限时本地 429(可配),并设
x-envoy-ratelimited等。 - 无外部限流服务;不能跨 Envoy 实例做精确全局配额。
5.2 Global(服务型)rate limit
- HTTP rate limit filter 按 route 的
rate_limits动作生成 descriptor,调用外部 Rate Limit Service(gRPC)。 - 配额状态在外部服务;可做多实例协同,但引入与 ext_authz 同类的可用性与延迟耦合。
- 与 local 可叠加:local 做紧急止血,global 做租户/API 级配额——分层思想与 25 文一致,实现落在两条 filter 路径。
| Local | Global | |
|---|---|---|
| 状态位置 | 本进程内存 | 外部 RLS |
| 跨实例一致 | 否 | 是(依赖 RLS) |
| 故障模式 | 随 Envoy | RLS 超时/错误策略 |
| 典型用途 | 单实例保护、简单路由配额 | 网格级、多代理共享配额 |
六、对照表与选型句
| 扩展 | 隔离 | 同进程? | 典型代价中心 | 信任假设 |
|---|---|---|---|---|
| 原生 C++ filter | 无额外沙箱 | 是 | 开发与发布周期 | 与 Envoy 同信任 |
| Lua | 弱(语言层) | 是 | 解释与 API 误用 | 运维可信脚本 |
| Wasm | VM 沙箱(实验中) | 是(VM 内) | ABI/延迟/实验性 | 半可信插件 |
| ext_authz | 进程外 | 调用外置 | 超时与 fail 模式 | 鉴权服务可信 |
| local ratelimit | 无 | 是 | 内存桶、不精确全局 | — |
| global ratelimit | 进程外 | 调用外置 | RLS 可用性 | RLS 可信 |
选型句:不可信多租户逻辑 → Wasm 或进程外服务,不要 Lua;强一致跨实例配额 → global RLS + 25 文中的算法陷阱;只防单实例过载 → local;身份/鉴权要独立演进 → ext_authz,并锁死与 route mutation 的顺序。
七、争论与开放问题
| 争论 | A | B | 落点 |
|---|---|---|---|
| Wasm vs 原生 filter | 隔离、多语言、热加载潜力 | 延迟、实验 API、运维工具链 | 热点路径慎用 Wasm(系列 16 再收束) |
| ext_authz vs 网关内建鉴权 | 策略中心化 | 多一跳故障 | 看 SLO 与团队边界 |
| Local vs Global 限流 | 简单可靠 | 配额准确 | 分层;算法见 25 |
开放问题:Proxy-Wasm ABI 与 Envoy Wasm filter 实验状态收敛后,是否足以在多租户网关上替代「旁路容器插件」——取决于隔离证明、尾延迟与生态稳定性,需跟踪实验特性毕业标准,而非假设「即将统一」。
八、参考资料
规范 / 官方文档(A)
- Envoy Proxy, Wasm HTTP filter, v1.39.0(experimental 声明)。
- Envoy Proxy, Lua HTTP filter, v1.39.0。
- Envoy Proxy, External Authorization HTTP filter, v1.39.0(含 route cache 安全节)。
- Envoy Proxy, Local rate limit / Rate limit HTTP filters, v1.39.0。
论文 / 站内(谱系)
- Haas et al., Bringing the Web up to Speed with WebAssembly, PLDI 2017(经 architecture/97 展开)。
- 限流与过载保护
源码(A)
envoyproxy/envoytag v1.39.0:source/extensions/filters/http/wasm/、lua/、ext_authz/、local_ratelimit/、ratelimit/。
实验台账
- 本篇无扩展延迟对比实测;不做 Wasm vs 原生排名。
九、小结
- 扩展先问挂点与信任域,再问实现语言。
- Wasm 提供进程内沙箱潜力,但仍是实验特性;细节沙箱语义回指 architecture/97。
- Lua 适合可信粘合;与 ext_authz 组合时必须防范 route cache 清空导致的鉴权绕过。
- Local/Global ratelimit 是算法(25)在数据面上的两种落点——进程内止血 vs 外部配额协同。
→ 系列目录 · 上一篇:Hot restart 与 drain · 下一篇:可观测数据面
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【Envoy 数据面】数据面全景:从 Listener 到 xDS 的可编程代理内核
定位 Envoy 相对 Nginx/HAProxy 静态配置代理与 Mesh 选型叙事的生态位;钉住请求路径、配置快照、FilterChainMatch、xDS warming、上游资源五条坐标系,并给出与 network/57 的分工及 16 篇阅读路线。
【Envoy 数据面】HTTP filter 链与 Router:顺序语义、终端过滤器与重试超时落点
钉住 HCM 内 HTTP filter 的 decoder/encoder 顺序、Router 作为终端过滤器的含义,以及 retry/timeout 挂在路由与 Router 上的语义;说明「Router 之后再挂 filter」为何无效,并为 Cluster 上游选型铺路。
Envoy / 数据面代理内核:从 Listener 到 xDS
补齐站内 Envoy 单篇地图与 Mesh/网关选型之间的数据面内核层:Main/Worker、FilterChainMatch、HCM、Cluster/连接池、xDS warming 与 Hot restart,并以排障与选型收束。
【Envoy 数据面】Main / Worker 与配置快照:事件循环、TLS 与几乎无锁热路径
钉住 Envoy 单进程多线程模型:Main 管 xDS/Admin,Worker 绑连接终生;Event::Dispatcher 与 Thread Local Storage 如何把配置变成每线程可读快照,以及快照解决什么、解决不了什么。