一次 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 治理,并不因为存在“业务网关”这个概念,就必须再串联一个网关服务。
这些都是职责上的选择,不能据此推导出任何系统都只需要一层代理。公网接入、内部访问和安全隔离要求不同,物理部署也可能不同。

图 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

图 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.1Host: api.example.comAuthorization: Bearer <token>下面是一份用于说明基本域名、路径路由的 Ingress 示例。它假设集群已有名为 higress 的 IngressClass,以及 demo 命名空间中的 order-service Service。Service 对外提供的端口是 8080。2
apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: order-entry namespace: demospec: 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 | 在哪里监听,连接使用怎样的过滤器链? |
| RDS | HTTP 请求匹配哪条路由? |
| 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
例如,用内存变量记录“当前租户已经退款多少次”,不仅无法跨副本共享,还把业务状态放进了一个可能更新、重启或被替换的执行环境。这个问题不是增加一把线程锁就能解决的,因为它首先是状态归属与持久化位置错误。

图 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

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

图 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

图 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 页面会随项目更新,具体部署请同时核对所用版本。