文章类型技术长文 所属专栏登神之路 预计阅读68 分钟 文档状态已更新
返回

登神之路 03:Higress——云原生网关的架构、机制与 Agent 实践

从 Envoy 数据面、Controller 与 Pilot 控制面、xDS 动态配置和 Wasm 插件,系统拆解 Higress 的请求链路、流量治理与 Agent 接入实践。

开始阅读全文13601 字 · 68 分钟 查看系列目录登神之路
关键词 HigressEnvoy云原生网关xDSWasmAgent
栏目 Backend;专栏 登神之路;标签 Higress、Envoy、云原生网关、xDS、Wasm、Agent

一次 HTTP 请求从客户端抵达后端,表面上只经历了“转发”,背后却有一连串决定:在哪里终止 TLS,如何匹配路由,从哪些实例中选择上游,什么时候拒绝请求,失败后是否重试,以及怎样观察整条链路。

Higress 把这些公共问题组织成一套网关系统。它源自阿里巴巴的网关实践,基于 Envoy 与 Istio 构建,既可以承接云原生应用的入口流量,也提供模型 API 和 MCP 工具接入能力。理解它的关键,不是记住插件名称,而是弄清楚:规则在哪里产生,请求在哪里执行,两者通过什么机制连接起来。1

本文先介绍网关本身的架构与运行机制,再用独立章节讨论它在 Agent 系统中的应用。文中的订单、退款场景均为机制讲解示例,不对应某家公司的真实部署。

技术资料核对日期:2026 年 9 月 13 日。本文使用 Higress 官方文档和 Envoy、Kubernetes 官方资料解释机制;不同 Higress 版本的插件字段、默认值与底层组件版本可能不同。示例中的服务名、额度和超时均为说明用途,不代表推荐的生产参数。

一、Higress 是什么?#

1.1 从反向代理到 API 网关#

反向代理首先解决的是接入问题。客户端访问一个公开地址,代理接收连接,再把请求转发给内部服务。客户端不必直接感知后端实例的地址变化,后端也不必让每个实例都独立暴露在公网。

但当服务数量、调用方和实例数量增加,转发本身就不够了。

例如,同一个域名下,/orders 应该进入订单服务,/users 应该进入用户服务;外部合作方只能访问开放接口,不能调用内部管理接口;某个租户突然发起大量请求时,系统需要控制其流量,而不能让所有租户一起受影响。这些需求都围绕请求发生,却不属于订单、用户等业务领域本身。

API 网关就是把这类公共接入与治理逻辑收拢起来。Higress 可以承担入口路由、微服务接入、认证与安全防护等职责,并通过插件扩展请求处理过程。1

可以把这层关系写成:

反向代理:接收请求,并转交给后端。
API 网关:在代理基础上,增加可配置的接入与治理策略。
Higress:实现上述能力的一套控制面、数据面和插件系统。

这里不是说“反向代理软件一定没有认证、限流”,而是区分我们讨论的职责层次。同一种代理内核,既可以只执行简单转发,也可以成为完整网关系统的数据面。

1.2 Higress 与 Nginx、Ingress 的关系#

讨论入口架构时,最容易把“配置规范”和“运行组件”画成同一条请求链路。

名称所处层次应当怎样理解
Kubernetes应用运行与资源管理平台管理 Pod、Service 等资源
Ingress / Gateway API入口与路由的资源模型描述入口应该具备什么行为
Ingress Controller / Gateway Controller对相应资源模型的实现监听配置,并推动网关形成相应行为
Nginx、Envoy代理软件可以实际接收和转发网络流量
Higress网关系统包含配置处理、代理转发和治理扩展等部分

Kubernetes 官方文档明确指出,只创建 Ingress 资源,并不会自动出现能处理流量的网关;还需要相应的控制器实现。Higress 则支持 Ingress 和 Gateway API,并以 Envoy 承接实际代理工作。21

因此,一种入口部署可以理解为:

客户端 → 外部负载均衡入口 → Higress Gateway → 后端实例

Ingress 规则属于旁边的配置输入,不是在 Higress 前面额外摆放的一台服务器。同样,Higress 可以同时承担入口路由和通用 API 治理,并不因为存在“业务网关”这个概念,就必须再串联一个网关服务。

这些都是职责上的选择,不能据此推导出任何系统都只需要一层代理。公网接入、内部访问和安全隔离要求不同,物理部署也可能不同。

Higress 在系统中的位置

图 01:Higress 在系统中的位置。

1.3 Higress 的核心设计#

Higress 的主体可以沿着三个问题展开。

**第一个问题是配置与执行如何分工。**管理界面和资源文件负责描述期望状态,控制面将其转换成代理可执行的配置,数据面使用已经获得的配置处理请求。配置处理不需要成为每次转发的中间步骤。3

**第二个问题是配置变化如何进入正在运行的代理。**服务扩缩容、路由调整、插件修改不应都等同于重新启动进程。Envoy 的动态配置体系允许不同种类的资源分别更新。4

**第三个问题是治理逻辑如何扩展。**Higress 使用 Wasm 插件承载多种请求处理能力,让扩展逻辑与代理内核拥有不同的开发和发布节奏。56

后面的模型协议适配、Token 治理和 MCP 接入,都可以放回这个基本结构理解,而不必把它们看成完全独立的另一套系统。

二、Higress 的整体架构#

2.1 数据面:Envoy#

数据面负责处理真正的业务流量。在 Higress 中,这部分以 Envoy 为核心。

从一个 HTTP 请求的视角,可以先认识五个对象:

对象作用
Listener定义在哪个地址和端口接收连接
HTTP Connection Manager管理 HTTP 连接、请求流与 HTTP 过滤器处理
Route根据请求属性决定路由行为
Cluster表示一组逻辑上的上游服务及其连接策略
Endpoint表示上游集合中可连接的具体地址与端口

这里的 Envoy Cluster 不是 Kubernetes 集群。前者是代理内部的上游抽象,后者是容器运行平台;两者只是恰好使用了同一个单词。7

Envoy 采用单进程、多工作线程的结构。主线程承担配置更新等协调工作,工作线程处理连接与请求;在典型连接处理模型中,一个已接收的连接会绑定到某个工作线程,并通过事件循环响应读写事件。8

这种结构不是“一个请求占住一个线程一直等待”。上游暂时没有数据时,工作线程仍能处理其他就绪事件。但这不代表网关容量无限:活跃连接、HTTP 流、缓冲区和插件计算仍然消耗资源。

理解这一点,也就能理解后文的插件约束:一个运行在请求处理路径上的同步重计算,可能拖慢同一工作线程上原本互不相关的请求。

2.2 控制面:Controller 与 Pilot#

控制面处理的是规则,不是订单查询结果。

Higress 的运行时配置文档将相关职责区分为 Controller、Pilot 和 Gateway:Controller 生成配置,Pilot 获取并过滤后向 Gateway 下发,Gateway 接收配置并用于路由。3

进一步看源码组织,pkg/ingress 包含 Ingress 资源转换逻辑,registry 对接服务发现来源,pkg/bootstrap 包含配置服务的启动代码。这些模块共同完成从外部资源到内部配置的转换。9

例如,管理员声明“某个域名下的 /orders 指向订单服务”,控制面需要把高层描述转换成路由与上游配置;订单服务增加实例后,又需要把发现到的地址变化传递给数据面。910

Console 是管理入口,Controller 与 Pilot 是配置处理角色,Gateway 是转发角色。**逻辑上分成几个角色,不意味着物理上必须部署同样数量的独立服务器。**在不同部署方式中,组件可能同 Pod 部署,也可能分别运行。3

网关侧还可能涉及 Pilot-Agent 等辅助组件。例如,官方 Wasm 下发机制中,Pilot-Agent 会参与配置代理和插件文件准备。它属于代理进程的管理辅助部分,不是业务请求必经的额外转发层,也不是第七章所说的业务智能体 Agent。6

Higress 控制面与数据面架构

图 02:Higress 控制面与数据面架构。

2.3 配置流与请求流#

理解整体架构时,应该始终保留两条不同的链路:

配置流:资源或管理操作 → Controller → Pilot → xDS → Envoy
请求流:客户端 → Envoy 中的过滤与路由逻辑 → 上游服务

客户端调用订单接口时,不会先请求 Controller 查询规则,再请求 Pilot 获取实例。代理已经持有相关配置,通常直接在数据面完成选择。37

这种分离使故障影响有所不同。假设代理进程仍在运行,也已经取得有效配置,控制面短暂不可达时,不一定马上停止已有转发;但新规则和新实例可能无法及时生效。xDS 服务短暂失联时,客户端会保留已有资源并尝试恢复连接,带有 TTL 等特殊生命周期的资源则需另行考虑。11

反过来,Gateway 进程退出,即使控制面仍然健康,也不能替它继续承接已经建立的连接。新启动的 Gateway 还需要获得启动所需配置,不能把“运行中的代理保留旧配置”理解成“任何新实例都能脱离控制面启动”。11

因此,“配置平台能打开”和“实际请求能成功”是两种不同的健康信号。排查时应分别观察规则输入、配置下发和数据面执行,不能只确认其中一处。

三、一次请求如何经过 Higress?#

3.1 连接接入与协议处理#

以一个查询订单的 HTTPS 请求为例。假设外部入口将连接交给 Higress,由 Higress 终止 TLS,那么代理首先完成连接接入与 TLS 握手,之后才能解析其中的 HTTP 请求。

TLS 终止在外部负载均衡还是 Higress,需要看实际部署;客户端到网关、网关到上游是否分别使用 TLS,也需要分别配置。不能因为入口地址是 HTTPS,就认定内部每一跳都已加密。Envoy 将下游连接和上游连接作为不同的连接处理。7

接下来,HTTP Connection Manager 将协议层数据组织成请求头、请求体和结束标记等事件,交给 HTTP 过滤器。过滤器不必直接处理 TCP 分包,便可以检查 HTTP 层信息。12

连接与请求也不能混为一谈。一条 HTTP/2 连接可以承载多个流,因此建立连接时完成的工作,与每个请求都需要执行的路由、鉴权并不是同一粒度。7

3.2 路由匹配#

假设请求为:

GET /orders/10086 HTTP/1.1
Host: api.example.com
Authorization: Bearer <token>

下面是一份用于说明基本域名、路径路由的 Ingress 示例。它假设集群已有名为 higress 的 IngressClass,以及 demo 命名空间中的 order-service Service。Service 对外提供的端口是 80802

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: order-entry
namespace: demo
spec:
ingressClassName: higress
rules:
- host: api.example.com
http:
paths:
- path: /orders
pathType: Prefix
backend:
service:
name: order-service
port:
number: 8080

它表达的是:将该域名下符合 /orders 路径前缀规则的请求路由到指定 Service。这里的端口是 Service 端口,不应直接理解成任意 Pod 的容器端口。示例没有配置 TLS、鉴权插件或路径重写;这些能力不会仅因为创建了这条路由就自动完成。2

Higress 还提供请求头匹配、灰度权重、路径和 Host 重写等治理配置。它们本质上都在改变请求的匹配条件或转发行为。13

需要注意,路由解析不一定是“所有插件跑完后才发生的一次固定动作”。部分过滤器会读取路由级配置,某些过滤器也可能改变路由相关信息。编写此类扩展时,必须保证前面的鉴权对象与最后真正访问的目标一致,避免先按一个低权限路由放行,随后又改去更敏感的路由。12

3.3 服务发现与负载均衡#

路由选中订单服务后,还没有完成最终转发。代理需要进一步知道,这个服务有哪些地址可以连接。

Higress 可以对接 Kubernetes 服务以及 Nacos、Consul、静态地址、DNS 等服务来源。发现与配置传播发生在控制和服务发现链路中,而不是要求每次业务请求都访问注册中心。1014

在 Kubernetes 中,Service 表示稳定的服务抽象,EndpointSlice 则记录相关后端端点及其状态。控制器可以根据这些信息,为代理生成上游端点配置。15

这里有一个非常重要的区别:

配置关系:路由引用 Service,Service 关联后端端点。
网络路径:实际数据包经过什么地址,要看代理获得的上游配置。

在代理直接获得后端 IP 和端口的模式下,Envoy 可以选中具体端点并发起连接,不能把 Service 画成一台必须经过的额外服务器。若配置让代理访问的是 Service 虚拟地址,则网络路径又会不同。应以 Gateway 实际获得的上游配置为准,而不是仅凭路由文件引用了 Service 就判断。31514

负载均衡也分两层语义:先确定目标服务或版本,再从其可用实例中选择一个。Higress 提供普通负载均衡和基于一致性哈希等配置方式,但算法选择解决的是分配策略,不替代实例是否可用的判断。13

3.4 请求转发与响应返回#

上游确定后,代理通过上游连接发送请求,接收响应,再经响应处理逻辑返回客户端。在这个过程中,连接池负责管理可复用的上游连接,HTTP 过滤器可以对请求和响应执行不同方向的处理。712

从逻辑上可以归纳为:

接收连接与解析协议
→ 读取路由及执行相关过滤逻辑
→ 选择上游与具体端点
→ 发送请求
→ 处理上游响应
→ 返回下游

一旦过滤器直接拒绝请求并生成本地响应,后续就不一定还会访问业务服务。因而,客户端看到一个错误状态码时,首先要判断它是网关生成的,还是上游返回的。1216

对于流式响应,代理不应被想象成“必须收齐一个完整字符串,再统一返回”。Higress 支持流式处理请求和响应体,但若某个插件主动聚合整个响应,它仍然可能改变端到端的流式行为。是否真正逐步到达客户端,要检查整条链路。117

一次请求的完整处理链路

图 03:一次请求的完整处理链路。

四、动态配置如何生效?#

4.1 xDS 的基本机制#

xDS 不是一种业务调用协议,而是 Envoy 获取动态资源的一组配置接口。其价值在于将原本写在静态代理配置中的不同对象,拆成能够独立发现和更新的资源。4

资源接口主要回答的问题
LDS在哪里监听,连接使用怎样的过滤器链?
RDSHTTP 请求匹配哪条路由?
CDS存在哪些上游 Cluster,各自采用什么策略?
EDS一个 Cluster 当前有哪些具体端点?
ECDS某个扩展过滤器应该使用什么配置?

这些资源通过名称引用彼此,而不是把全部配置压成一条模糊的“转发规则”。例如,路由引用某个 Cluster,Cluster 再关联具体端点;插件配置也可以通过扩展配置发现机制获得。46

在典型 gRPC xDS 模式中,代理与配置服务维持配置通信,更新到来后进行解析和处理。客户端会通过 ACK 或 NACK 反馈接收处理结果。版本信息与请求标识帮助双方关联更新,但 ACK 并不等价于“真实业务已经完成端到端验证”。11

4.2 路由变更与服务扩缩容#

先看增加路由的情形。管理员提交新规则后,控制面将其转换成内部配置,再把相关更新传递给数据面。数据面获得所需的路由和上游资源后,后续符合条件的请求才有可能按新规则处理。39

再看服务从两个实例扩容到四个实例。业务路由本身可能完全没有变化,变化的是上游端点集合。此时重点是发现新增地址,并使数据面获得新的端点信息,而不是无条件重建全部监听器和路由。154

因此,一次变更至少有几个不同的观察位置:

原始规则是否正确
→ Controller 是否完成转换
→ Pilot 是否获得并下发相关配置
→ Gateway 是否接受配置
→ 实际请求是否命中预期行为

Higress 官方提供了查看 Controller、Pilot 和 Gateway 运行时配置的方式。遇到“控制台保存成功,但请求还是旧行为”,沿这些位置比对,比反复重新保存规则更容易定位问题。3

动态配置下发与服务扩容时序

图 04:动态配置下发与服务扩容时序。

4.3 动态更新与长连接#

动态配置对长连接的意义,可以用一条正在输出结果的请求来解释。

假设请求 A 已经路由到旧版本服务,并持续接收响应;此时管理员调整路由,让后续请求进入新版本。RDS 支持运行时替换路由配置,而不影响已经在处理的请求。因此,请求 A 不需要仅因为路由规则变化就被重新执行。18

这里的粒度是“正在处理的请求”,不应简单写成“旧连接永远使用旧路由”。一条可复用连接上后来发起的新请求,仍可能匹配新的规则。

同样,配置更新不会把一个正在旧实例上执行的任务自动迁移到新实例。如果旧上游本身被关闭,或者代理进程被强制终止,原来的请求仍可能失败。动态配置解决的是更新配置的方法,不提供计算任务迁移能力。

不同资源的更新行为也不同。Envoy 文档区分了 RDS、EDS 与 CDS:路由可以平滑替换;EDS 调整端点时,不必影响集合中其余已有端点;某些 Cluster 配置更新则会触发连接池排空和重建。419

这也不是“Nginx 一 reload 就一定断开所有连接”的对比。Nginx 本身具有优雅重载机制,旧工作进程可以继续处理已有客户端。更准确的区别是:Higress 的动态资源体系,让许多规则变化不必依赖整个工作进程代际切换。20

路由更新与正在执行的长请求

图 05:路由更新与正在执行的长请求。

4.4 多副本下的配置与状态#

多个 Gateway 可以接收同一套期望配置,但配置传播仍然需要时间,不能把它当成多个进程之间的一次全局原子切换。xDS 提供配置更新与资源协调机制,并不等于所有副本在同一时刻执行同一版本的规则。11

更重要的是,配置相同不代表所有运行状态也相同。

状态是否因为下发相同配置就自动共享?
路由与插件规则可以下发同一份期望配置,但存在传播过程
已建立连接、在途请求不会因此迁移到其他副本
插件本地缓存、进程内变量不会因此成为跨进程共享数据
租户全局限流计数需要共享计数或其他分布式协调机制
订单状态、退款结果应由业务系统持久维护,不属于代理配置

例如,每个副本都配置“租户每秒允许 100 个请求”,若计数完全在各自本地进行,三个副本合起来可能放行远超 100 个请求。要表达整个网关集群范围内的统一额度,需要额外的共享计数机制。Higress 的集群限流插件正是通过 Redis 协调这类状态。21

所以,“网关便于扩容”与“网关没有状态”不是一回事。真正需要区分的是:哪些状态只服务于当前连接,哪些状态必须跨副本协同,哪些状态应当交还业务系统。

五、Wasm 插件机制#

5.1 插件运行在哪里?#

网关插件需要介入请求,但并不意味着每个插件都是一个独立的 HTTP 服务。

Higress 的 Wasm 扩展会被编译成 WebAssembly 模块,交给 Envoy 进程中的 Wasm 运行时加载。模块通过 Proxy-Wasm 提供的接口与宿主交互,读取或修改请求信息,调用受支持的宿主能力。这里的沙箱是执行环境,不是“每来一个请求就创建一个容器”。22

对常见的 HTTP 插件,可以分清三个层次:

层次关注的内容
VMContext模块与虚拟机级别的初始化
PluginContext插件配置及相应运行上下文
HttpContext当前 HTTP 请求流的处理状态

这些上下文是 Higress Go 插件开发模型中的概念。每个请求都需要自己的处理状态,但不意味着每次请求都重新创建一个完整 Wasm 虚拟机。23

Wasm 实例与 Envoy 工作线程的组织方式也很重要。官方原理文档介绍了线程侧的虚拟机实例,以及符合条件的插件共享虚拟机的情形。因此,插件中的一个普通全局变量,不能直接当成整个 Gateway 的唯一共享变量,更不能当成多个 Gateway 副本的统一状态。22

例如,用内存变量记录“当前租户已经退款多少次”,不仅无法跨副本共享,还把业务状态放进了一个可能更新、重启或被替换的执行环境。这个问题不是增加一把线程锁就能解决的,因为它首先是状态归属与持久化位置错误。

Wasm 运行时与请求上下文

图 06:Wasm 运行时与请求上下文。

5.2 插件如何介入请求处理?#

HTTP 过滤器可以在请求头、请求体、响应头和响应体等阶段介入。对于同时参与请求与响应的过滤器,解码方向和编码方向的执行顺序不同:若请求依次经过 A、B、C,响应通常按照 C、B、A 返回。只有单向能力的过滤器、本地生成的响应等情况,还需要结合具体处理路径分析。12

插件顺序不是装饰性的排列。假设一个插件从令牌中提取可信身份,另一个插件按身份限制额度,那么身份识别通常就需要先于相应的额度判断完成。Higress 采用的 WasmPlugin 配置体系具有执行阶段与优先级等控制方式,不能只凭配置文件的书写顺序判断实际执行顺序。24

还要区分两件事:**配置适用范围决定使用哪份配置,执行顺序决定插件何时运行。**Higress 支持全局、域名和路由等范围的插件配置匹配,认证类插件还具有需要单独理解的配置规则。这与过滤器的先后次序不是同一个维度。5

有些插件需要访问外部服务,例如查询一个授权结果。正确思路不是阻塞工作线程等待,而是利用宿主提供的异步调用能力,暂停当前请求的后续处理,在回调中恢复或结束请求。Higress Go SDK 为这类 HTTP 调用提供了客户端与回调封装。14

下面是机制伪代码,不是可以直接编译的 SDK 示例:

收到请求头:
发起有超时限制的外部认证调用
暂停当前请求继续执行过滤器链
认证调用回调:
若当前请求已经结束:停止处理
若认证失败或超时:返回明确的失败响应
若认证成功:记录可信身份,恢复当前请求处理

暂停的是当前请求的处理进度,不应变成让整个工作线程睡眠。否则,同一线程承接的其他连接也会受到影响。编写插件时,除了成功回调,还应处理超时、错误和请求提前结束的路径。814

过滤器顺序与异步调用

图 07:过滤器顺序与异步调用。

5.3 隔离与热更新#

插件发布包含两类变化:一类是修改已有插件的参数,另一类是更新插件代码本身。两者都可能影响流量,但排查对象不同,不能混成一次笼统的“更新网关”。

Higress 官方文档描述了通过 ECDS 下发 Wasm 插件的过程:插件声明进入控制面后,相关配置经发现服务传递;网关侧的 Pilot-Agent 可以下载 OCI 制品中的 Wasm 文件,准备本地路径,再交给 Envoy 加载。OCI 在这里用于分发插件制品,并不表示业务请求要进入一个插件容器执行。6

可以把核心过程理解为:

发布 Wasm 制品 → 更新插件声明 → 分发扩展配置
→ 网关准备模块文件 → Envoy 加载并应用

这种机制让插件发布不必总是伴随整个代理进程重启。不过,“支持热更新”不应该成为跳过验证的理由。代码是否与当前运行时兼容、配置能否解析、模块能否取得、异常时如何影响请求,都需要结合具体版本和插件行为测试。

在发布实践上,建议固定可追踪的制品版本或摘要,先在有限流量中验证,再逐步扩大范围。这是控制更新风险的工程建议,不是说只要使用 Wasm,系统就自动获得灰度发布和可靠回滚。

沙箱隔离也有明确边界。它限制模块的执行与内存访问方式,但插件仍然消耗 CPU、内存,并能通过允许的宿主接口处理请求数据。错误的权限逻辑、过量的请求体缓冲、没有边界的外部调用,并不会因为代码运行在 Wasm 中就消失。2217

Wasm 插件下发与热更新

图 08:Wasm 插件下发与热更新。

5.4 插件的能力边界#

判断某段逻辑是否适合放进网关,可以先问两个问题:它是否围绕当前请求的接入与转发发生?它是否能够在明确的时间和资源预算内完成?

身份识别、轻量参数转换、访问策略、限流和指标提取,通常符合这个边界。完整业务事务、持久任务编排和长时间推理,则不宜仅因为存在扩展接口,就默认放入代理进程。

特别要注意请求体处理的成本。假设某插件为每个在途请求保留 64 KiB 数据,恰好有 10,000 个请求同时保留这部分内容,仅这些数据就约占 625 MiB,尚未计算连接、对象和运行时开销。这是一个说明内存放大效应的算例,不是 Higress 的实际资源消耗测量。

Envoy 的流控与缓冲机制能够帮助管理上下游速度差异,但插件主动要求收齐完整内容时,仍需要设置合理边界。流式转发能力与“插件可以无限积累数据”不能同时成立。17

因此,插件设计应尽量让耗时、缓冲量、外部调用次数和失败行为可解释。网关是许多请求共同经过的位置,一个局部扩展的成本,会乘上经过它的并发请求数量。

六、流量治理与可观测性#

6.1 身份认证与访问控制#

身份认证回答“调用者是谁”,授权回答“调用者可以做什么”。在网关与业务系统之间,还应该进一步区分通用接口权限与具体资源权限。

例如,一个合作方获得了订单查询 API 的使用资格,不等于它可以查询任意租户的订单。网关可以验证调用身份和接口访问范围,订单服务还必须检查目标订单是否属于当前调用方允许访问的资源。

Higress 提供 JWT 等认证插件。JWT 插件可以根据消费者配置验证令牌,并按照路由或域名配置允许访问的消费者;验证成功后,可以通过 X-Mse-Consumer 等约定信息向后续处理环节传递消费者身份。具体字段和规则应以所使用版本的插件文档为准。25

这里必须建立可信边界:不能因为请求里出现了一个内部身份头,就直接相信它。一个合理的部署要求是,由可信入口验证身份并处理保留字段,后端只接受符合信任关系的请求路径,同时继续检查业务资源权限。这是完整链路需要保证的约束,不能假定任意部署都会自动正确处理。

同理,TLS 提供传输安全,不自动解决租户隔离;模型服务的 API Key 能证明应用有权调用模型,也不自动证明某个终端用户有权修改某笔订单。

6.2 限流与多副本协同#

限流不是只有一个“每秒多少次”的数字,还必须回答三个问题:按谁计数,在哪个范围共享计数,超过限制时怎样处理。

Higress 的本地 Key 限流插件支持围绕请求头、请求参数等维度配置请求额度;集群 Key 限流插件则使用 Redis 协调计数,支持整体规则与特定请求属性等限流方式。两者最重要的区别,是状态作用范围,而不是名字里有没有“高级”二字。2621

假设有三个 Gateway 副本:

每个副本本地限制 100 次/秒
≠ 整个集群合计限制 100 次/秒
多个副本使用同一套集群规则与共享计数
→ 才能围绕集群总额度进行协调

这是范围上的区别,不是对所有算法在任何时间边界下的精确放行量承诺。

本地限流适合约束单实例压力,共享限流适合表达租户、调用方等维度的统一额度。两者可以服务于不同目标,而不是必须二选一。

分布式限流还引入一个新依赖:共享计数服务。Redis 的延迟、故障、热点键,以及身份键是否可信,都会影响治理效果。不能让客户端随意填写一个“租户 ID”,就绕开应该共享的额度。

因此,落地时要明确异常策略:共享计数不可用时,是拒绝相关请求,还是允许经过受限的降级路径;这需要结合接口风险与具体插件能力设计,不能把某一种处理当成所有插件的默认行为。

本地限流与分布式限流

图 09:本地限流与分布式限流。

6.3 超时、重试与故障处理#

“把超时调大一点”往往不能解决问题,因为链路里有多种不同的时钟。Envoy 文档区分了连接建立、路由等待、单次重试、流空闲和流生命周期等超时概念。27

时间约束主要限制什么容易产生的误解
上游连接超时与上游建立连接的等待时间连接成功,不代表业务会及时返回
路由超时等待上游完成响应的时间不应直接当成整个 Agent 任务的期限
单次尝试超时一次上游尝试的预算不能与总预算分别任意增大
流空闲超时一段时间没有流活动与请求已经持续多久不是同一概念
流最大持续时间整个流允许存在的最长时间即使持续有数据,也可能达到上限

具体开启情况与默认值需要检查 Higress 生成的配置,不能把某个 Envoy 文档中的默认值直接当成当前网关的最终行为。对于 SSE,尤其需要同时关注“很久没有输出”和“整个流持续过久”这两类问题。27

重试也必须放进同一份时间预算。例如,下面是人为设定的预算示例:

本次调用总预算:3 秒
第一次尝试:最多 1 秒
退避等待:0.2 秒
第二次尝试:最多 1 秒
其余时间:留给连接、代理处理与响应返回

重试不是新的免费时间,也不是每类错误都适合重复提交。Envoy 具有可配置的重试条件、次数等机制,但最终要结合请求语义决定哪些失败能够安全重试。28

最重要的一点是:**调用方超时,只能说明它没有在预算内得到确定结果,不能证明上游没有执行。**如果业务已经提交成功,但响应在网络中丢失,再次创建一笔新操作,就可能造成重复副作用。查询请求与退款、下单等写操作应分别设计。

还要区分几种经常被统称为“熔断”的机制。Envoy 的 Circuit Breaker 主要围绕连接、排队请求、并发请求和重试等资源设置上限;异常实例摘除根据运行中的失败信号暂时排除有问题的端点;主动健康检查则由代理发起探测。这三者关注的对象并不相同。Higress 是否暴露对应配置、采用什么参数,需要检查具体部署,不能把底层具备的能力全部视为默认开启。293031

超时预算与重试

图 10:超时预算与重试。

6.4 日志、指标与链路追踪#

日志、指标和追踪不是同一种数据的三个展示页面,它们回答的问题不同。

**日志用于还原一条请求。**网关访问日志可以帮助确认请求匹配、响应结果和上游访问情况;控制面日志则帮助定位配置处理与下发问题。Higress 的日志文档分别介绍了相关组件的日志与访问日志配置。16

**指标用于观察一群请求。**请求量、错误率、延迟分布等适合做趋势和告警。Higress 提供 Prometheus 对接方式,但采集、标签和展示仍需要实际配置,安装了网关不代表已经完成监控体系建设。32

**链路追踪用于关联多次调用。**一次外部请求进入业务服务后,可能继续访问多个下游。Envoy 可以参与追踪,但应用需要正确接收与传播追踪上下文,才能把后续调用连起来;不能指望网关自动理解应用内部的所有任务关系。33

排查一次请求变慢时,可以沿着证据缩小范围:先确认是所有路由变慢还是某个路由,再比较网关和上游相关耗时,随后检查对应日志与调用链。对于流式请求,还应分别看首次输出与整体结束,而不是只看总耗时。

标签设计也需要克制。路由、服务、状态码等相对稳定的维度适合聚合;订单号、请求 ID 和原始提示词通常不适合直接作为指标标签。具体请求标识更适合进入可检索日志或追踪记录,同时落实脱敏与访问控制。

最终,观测应该回答的是“哪一层、什么原因、影响哪些请求”,而不是只留下一个无法解释的错误数量。

日志、指标与链路追踪

图 11:日志、指标与链路追踪。

七、Higress 在 Agent 系统中的应用#

7.1 模型调用的统一入口#

进入 Agent 系统后,网关可以出现在三个不同的逻辑位置:用户访问 Agent 的入口、Agent 访问模型的出口,以及 Agent 访问工具的出口。Higress 的普通 API、模型 API 与 MCP 接入能力,可以分别用于这些位置。1

用户 → 入口网关 → Agent Runtime
├─ 模型网关 → 模型服务
└─ 工具网关 → MCP Server / 业务 API

这表示三类职责,不意味着必须部署三套 Higress。是否拆开部署,应根据公网暴露、权限边界和资源隔离要求决定。

在模型侧,AI Proxy 插件提供服务商接入、鉴权配置、协议适配和模型名称映射等能力。Agent 可以使用一个稳定的逻辑模型名,再由网关映射到实际提供服务的模型,减少业务代码直接绑定服务商细节的程度。34

例如,下面是人为设计的逻辑模型别名,不是 Higress 内置名称:

Agent 请求:customer-service-fast
网关映射:当前选定的客服模型
上游调用:对应服务商的模型 API

不过,接口格式适配不能代替能力验证。工具调用、结构化输出、参数限制与流式行为都可能存在差异。替换上游之前,仍应确认 Agent 依赖的行为能够成立,不能因为 HTTP 请求发送成功,就认定模型之间可无损替换。34

模型回退同样存在输出边界。在尚未向调用方提交响应时,某些失败可以按策略切换上游;已经输出部分内容后,再请求另一个模型,不能自动变成原有回答的无缝续写。应用必须决定是明确失败、重新生成,还是采用专门的恢复流程。这个边界来自响应已经开始提交的事实,而不是增加一个重试次数就能消除。28

对于用量治理,Higress 的 AI Token 限流插件使用 Redis 进行协调,支持按消费者或请求属性等维度控制 Token 消耗,并依赖 AI Statistics 获取相应消耗信息。它解决的是模型调用资源治理问题。35

这里还需要区分流量额度与严格账本。生成完成前,最终输出量未必已知;并发请求、失败重试和中途取消,也可能让用量归属更复杂。因此,不能仅凭开启一个限流插件,就承诺实现绝对不超额的预扣款与精确结算。需要严格成本控制时,还应设计预算预留、实际用量归集与异常对账。

Higress 在 Agent 系统中的接入位置

图 12:Higress 在 Agent 系统中的接入位置。

7.2 MCP 与工具接入#

在工具侧,Higress 可以代理已有 MCP Server,也可以通过 MCP Server 插件将 REST API 映射为工具。官方插件配置区分了相应服务类型,并提供工具定义、请求模板与响应处理等能力。36

假设订单系统已经提供:

GET /orders/{orderId}/status

面向 Agent 时,可以把它描述为一个有明确语义的工具。以下是工具契约示意,不是可直接粘贴的 Higress 插件配置:

工具名:get_order_status
用途:查询当前调用者有权访问的订单状态,不修改订单。
输入:orderId,必填字符串。
输出:订单状态、是否发货、查询时间等必要信息。
后端映射:GET /orders/{orderId}/status

执行时,工具调用中的参数经过校验与模板映射,形成访问后端接口的请求;返回结果再整理为工具调用方能够使用的内容。需要注意,官方快速接入文档明确提醒,请求模板中的 URL 不会替代路由配置所绑定的目标服务,不能把“模板里写了某个地址”当成已经完成服务路由。37

Higress 还提供从 OpenAPI 文档生成 MCP 配置的工具,但自动生成解决的是适配工作量,不是业务设计。工具描述是否明确、参数是否受约束、分页是否有上限、返回结果是否暴露多余字段,仍然需要检查。37

对有副作用的接口,应进一步缩小暴露范围。一个名为 execute_any_api、允许模型自由拼接目标地址和请求体的工具,与一个限定订单、操作类型和参数的退款申请工具,风险边界完全不同。应优先暴露明确、有限的业务能力,而不是把整个内部网络变成可任意访问的工具面。

工具访问控制也不应只做在“是否可以建立 MCP 连接”这一层。还要检查具体工具权限与资源权限。Higress 的 MCP 插件提供工具过滤配置,但业务服务依然需要验证资源归属和操作条件;协议转换本身不能证明调用合法。36

HTTP API 到 MCP 工具的映射

图 13:HTTP API 到 MCP 工具的映射。

7.3 流式交互与调用观测#

Agent 系统中至少要区分两段流:一段是模型向 Agent 输出内容,另一段是 Agent 向用户输出交互事件。两者不一定原样透传。

例如,模型流中可能出现工具调用参数,Agent 收齐并验证后才发起查询;用户侧收到的则可能是“正在查询订单”、查询结果和最终回答。中间的进度事件由应用组织,不应把内部工具参数或模型中间信息全部暴露给用户。

实现时,需要按协议组装完整事件,不能将一次网络读取当成一个完整语义单元。SSE 以文本行和事件分隔规则组织数据,底层网络分块与事件边界并不一一对应。流式工具参数也应完成组装和校验后,再交给执行逻辑。38

链路上的缓冲会影响体验。某个插件等待收齐整个响应,或者应用没有及时向客户端刷新数据,都可能让底层“支持流式”变成用户眼中的长时间等待。Envoy 的流控机制可以调节上下游传输,但应用组织事件和插件处理内容的方式同样重要。17

取消与断连也需要贯穿应用设计。用户关闭页面,不代表已经发起的工具操作自动撤销;模型请求能够取消,也不代表一笔已经受理的业务操作能够回滚。建议由 Agent Runtime 传播取消信号、停止不再需要的后续计算,并保留已经提交的写操作状态以供查询。

在指标上,AI Statistics 插件能够记录模型输入与输出 Token、流式首 Token 耗时和总请求耗时等信息。39 但网关测得的首 Token 时间,与用户看到第一个有效内容的时间可能不同,因为中间还经过 Agent 的处理与另一段响应链路。

因此,排查交互延迟时,应至少区分模型首输出、工具等待和应用首可见事件。流式响应已经返回 HTTP 200,也不能单凭这个状态认定后续内容完整或任务成功,还需要结合流结束状态与应用结果判断。

模型输出流与用户事件流

图 14:模型输出流与用户事件流。

7.4 Agent、网关与业务服务的职责边界#

对于需要明确状态和副作用控制的业务,可以采用下面的分工:

角色主要职责不应仅依靠它完成的事情
Agent Runtime组织上下文、解析模型输出、安排工具调用、管理任务进度将模型判断直接当成业务授权
Higress接入认证、协议适配、路由、额度与调用观测用一次请求成功替代完整任务成功
业务服务校验资源权限、执行业务规则、持久化状态、保证幂等相信调用来自 Agent 就跳过正常校验

这是一种架构分工建议,不是说 Higress 技术上完全无法执行 Agent 逻辑。官方本身提供 AI Agent 插件,支持配置 GET、POST 类型工具,进行多轮调用,并提供流式与非流式模式。40

不过,当任务需要跨请求恢复、等待人工确认、执行长时间流程或保证业务副作用可追踪时,仍然应明确这些状态由哪个可靠的业务或工作流组件持久保存,不能只因为插件具备多轮调用能力,就认为整套任务可靠性设计已经完成。

重试是最容易跨层失控的例子。假设 Agent 一次工具操作最多发起 3 次尝试,网关每次又最多向上游发起 2 次尝试,两个数字都包含首次调用,那么理论上就可能形成 6 次上游尝试。这个乘法与具体网关品牌无关,是多层策略叠加的结果。

所以,Agent 与网关需要共同遵守任务期限和重试预算。对于写工具,更关键的是多次尝试应代表同一笔业务意图,而不是每次都创建一个新的操作。

一个可用于理解幂等的业务设计是:为操作生成稳定的请求标识,将它与租户、操作类型及参数摘要一起保存;业务服务利用唯一约束和事务保证重复请求返回同一个操作结果。若相同标识对应不同参数,则拒绝混用。对于异步副作用,还需要让操作记录与后续可靠投递协调,而不能只在网关内存里记住“处理过”。

身份同样需要贯穿链路。租户、终端用户和应用身份是不同维度:一个 Agent 应用持有的模型密钥,不能替代用户资源权限;模型生成的 userId,也不能直接覆盖经过认证的调用身份。工具执行应使用由可信应用上下文确定的权限范围。

7.5 示例:智能客服查询订单并申请退款#

以下是一个用于说明机制的设计示例,不是 Higress 的默认业务流程,也不是某家公司的真实退款系统。

用户提出:

“帮我查一下订单有没有发货;如果还没发货,我想申请退款。”

**第一步,入口接入与任务建立。**请求经入口网关完成必要的身份验证与流量限制,再进入 Agent。Agent 建立可追踪的任务标识,并把用户身份与允许访问的租户范围作为可信上下文保存,而不是让模型自行推测。

**第二步,模型提出查询。**Agent 经模型网关调用模型。模型提出 get_order_status 工具请求,Agent 检查工具是否允许调用、参数是否完整,再通过工具网关访问订单服务。订单服务检查资源权限后返回当前状态。

这里的调用关系是:

模型提出调用意图
→ Agent 验证并发起工具调用
→ Higress 适配和转发
→ 业务服务校验并执行
→ 结果返回 Agent

模型没有直接获得数据库写权限,网关也没有替订单服务决定某个用户能否查看目标订单。

**第三步,确认退款意图与业务条件。**假设订单尚未发货,Agent 根据业务服务返回的规则结果向用户展示可申请操作。如果业务要求二次确认,确认应绑定明确的订单与操作范围,并由应用验证,不应只接受模型生成的一个 confirmed=true

初次查询结果只是当时的快照。真正提交退款申请时,业务服务仍需重新检查订单状态,并以原子方式协调退款申请与发货等并发操作,防止查询后状态已变更,却继续按旧结果执行。

**第四步,以稳定标识提交写操作。**Agent 为这一笔退款申请使用稳定的幂等标识。Higress 完成接入、权限策略和协议适配后,由业务服务校验确认凭据、资源归属与退款条件,再记录操作。

如果业务采用异步处理,应返回明确的申请或操作标识,以及“已受理”“处理中”等状态。Agent 必须区分“申请已受理”和“退款已完成”,不能因为 HTTP 调用成功,就告诉用户款项已经到账。

第五步,处理三种不同的故障。

故障本示例的处理思路不能混淆的边界
模型服务暂时不可用在预算内选择允许的回退或结束本轮调用已输出一半的回答不能被假定可无缝续写
订单查询超时在读取语义与时间预算允许时重试新查询可能看到比上次更新的状态
退款申请超时保留原幂等标识,查询操作状态;必要时按幂等协议重试没收到响应不等于退款申请没有提交

对于最后一种情况,可以把任务标记为“结果待确认”,而不是立即当成失败并创建第二笔退款申请。用户断开连接后,已经提交的业务操作也需要能够继续被追踪;再次进入会话时,通过任务标识和业务操作标识恢复展示状态。

**第六步,关联整条任务链。**一次客服任务可能包含多个模型请求与工具请求,所以既要有单次调用的 Trace,也要有贯穿多次调用的任务标识。一个简化的关联示意是:

任务 task-123
模型调用 model-call-1
订单查询 tool-call-1
用户确认 confirmation-1
退款申请 tool-call-2 → 业务操作 refund-op-456
状态查询 tool-call-3 → 同一业务操作 refund-op-456

这些名称仅用于说明关联关系,不是 Higress 自动生成的固定字段。日志中记录必要的关联标识即可,不应为了“可观测”无边界保存用户敏感信息、密钥或完整工具输入。

智能客服订单查询与退款申请时序

图 15:智能客服订单查询与退款申请时序。

回到 Higress 本身,它的价值在于将配置管理、代理转发和扩展治理组织在明确的边界内。控制面决定规则如何进入代理,数据面执行请求处理,插件扩展公共能力。进入 Agent 系统后,这套结构继续服务于模型与工具调用,而业务状态、任务恢复和操作权限仍需要各自可靠的实现。

理解 Higress,不只是理解一个请求怎样被转发,更是理解:一项策略应该在哪一层生效,一份状态应该由谁保存,一次失败应该由谁负责恢复。


参考资料

以下为正文引用的官方文档,核对日期为 2026 年 9 月 13 日。latest 页面会随项目更新,具体部署请同时核对所用版本。

Footnotes#

  1. Higress:Higress 是什么? 2 3 4 5

  2. Kubernetes:Ingress 2 3

  3. Higress:查看运行时配置 2 3 4 5 6 7

  4. Envoy:Dynamic configuration 2 3 4 5

  5. Higress:Wasm 插件使用简介 2

  6. Higress:Wasm 生效原理 2 3 4

  7. Envoy:Life of a Request 2 3 4 5

  8. Envoy:Threading model 2

  9. Higress:源码阅读指引 2 3

  10. Higress:Mcp Bridge 配置说明 2

  11. Envoy:xDS REST and gRPC protocol 2 3 4

  12. Envoy:HTTP filters 2 3 4 5

  13. Higress:通过 Ingress Annotation 实现高阶流量治理 2

  14. Higress:Wasm 插件 HTTP 调用 2 3 4

  15. Kubernetes:EndpointSlices 2 3

  16. Higress:日志说明 2

  17. Envoy:Flow control 2 3 4

  18. Envoy:Route discovery service (RDS)

  19. Envoy:Cluster discovery service (CDS)

  20. NGINX:Controlling nginx

  21. Higress:基于 Key 的集群限流 2

  22. Higress:Wasm 插件原理 2 3

  23. Higress:插件 Go SDK 与处理流程

  24. Istio:WasmPlugin

  25. Higress:JWT 认证

  26. Higress:基于 Key 的本地限流

  27. Envoy:How do I configure timeouts? 2

  28. Envoy:HTTP routing 2

  29. Envoy:Circuit breaking

  30. Envoy:Outlier detection

  31. Envoy:Health checking

  32. Higress:基于 Prometheus 实现入口流量观测

  33. Envoy:Tracing

  34. Higress:AI 代理 2

  35. Higress:AI Token 限流

  36. Higress:MCP Server 插件配置 2

  37. Higress:MCP 快速开始 2

  38. WHATWG HTML Standard:Server-sent events

  39. Higress:AI 可观测

  40. Higress:AI Agent

登神之路 03:Higress——云原生网关的架构、机制与 Agent 实践
https://jupiter-ws.cn/posts/backend/road-to-god/03_higress_cloud_native_gateway/
作者
Jupiter
发布于
2026-09-13
许可协议
CC BY-NC-SA 4.0