首页 / 资讯中心 / 文章详情

Higress云原生API网关深度解析:架构、原理与落地实践

Higress云原生API网关深度解析:架构、原理与落地实践 ★ FEATURED ARTICLE
刚接手一个维护了几百个微服务的团队时最头疼的其实是入口这层线上既有 Nginx Ingress 在管 Kubernetes 南北向流量又有一套自建的微服务网关在处理鉴权、限流和路由两套系统各有各的控制面配置规范还完全不同。后来团队统一切到 Higress才算把这套“双网关”的复杂度真正压下来。Higress 是一个基于 Istio 和 Envoy 构建的云原生 API 网关由阿里云开源并捐赠给 CNCF它最大的特点是把 Kubernetes Ingress、Gateway API 和微服务网关的能力收敛到了一套控制面和数据面上。这篇文章我会从架构骨架、请求处理链路、插件机制、选型对比和落地踩坑几个维度把 Higress 的底层原理彻底拆开聊一遍。无论你是正在做网关选型还是已经上了 Higress 但只停留在“会用 Ingress 注解”的阶段这篇文章都值得读完。我会尽量用实际运维中遇到的场景来解释原理而不是背书式的概念堆砌。1. 先从整体架构说起Higress 的控制面与数据面1.1 控制面由谁组成Higress 的控制面不是一个单体组件而是由 Higress Controller 和 Istio Pilot 两个核心进程协作完成的。很多人第一次接触 Higress 时会困惑为什么已经用了 Istio还要单独跑一个 Controller我一步步拆。Higress Controller 负责监听各种配置源包括 Kubernetes 的 Ingress 资源、Gateway API 资源、Higress 自定义的 CRD比如 HigressListener、HigressRoute以及服务注册中心里的实例变化。它把这些不同来源的配置统一转换成 Istio 的 VirtualService、Gateway 和 DestinationRule 等模型再提交给 Istio Pilot。Istio Pilot 则负责把这些高层模型翻译成 Envoy 能识别的 xDS 配置LDS、RDS、CDS、EDS 等并通过 xDS 协议推送给数据面。也就是说Higress Controller 做的是“语义转换”Istio Pilot 做的是“协议下发”两者职责不同互相配合。这种分工有一个很实际的好处如果未来 Istio 生态出现了新的数据面能力比如更精细的负载均衡策略Higress 不需要重写整套逻辑只要让 Controller 生成对应的 Istio CRD 就能继承能力。我实测下来这种“站在 Istio 肩膀上”的设计让 Higress 的功能迭代速度比传统网关要快很多。1.2 数据面为什么选 Envoy数据面几乎没有任何悬念地用了 Envoy。Envoy 本身就是为云原生场景设计的代理它原生支持 xDS 协议进程内自带热更新机制配置变更时不会断连接这对于网关这种 7x24 小时在线的组件来说是刚需。更关键的是Envoy 的网络模型非常清晰Listener 负责接收连接Filter Chain 负责对流量做处理Cluster 负责定义上游服务。Higress 的所有路由、限流、灰度、鉴权能力最终都是在这套模型上以 Filter 的形式实现的。后面你会发现理解了 Envoy 的这三个概念就等于理解了 Higress 一半的运行原理。另外一个现实原因是性能。Envoy 底层用 C 编写线程模型是主线程加 worker 线程池每个 worker 独立处理连接锁竞争少长连接场景下的表现很稳。我们压测过同样的机器配置下Higress 的 QPS 和延迟表现明显优于纯 Lua 脚本型的传统网关。1.3 控制面与数据面如何联动控制面和数据面之间不是简单的“下发配置”关系而是一个持续循环的过程。我画一条链路帮助理解Higress Controller 监听到 Ingress 或 CRD 变化转换成 Istio 模型Pilot 再转成 xDS 配置推给 Envoy。Envoy 加载新配置后通过增量 ACK 告诉 Pilot “我收到了”Pilot 更新状态Controller 再把最终状态写回 Kubernetes 的 status 字段。高版本里为了让这套流程更稳默认启用了 MCPMesh Configuration Protocol协议走增量推送。如果你在排查配置没生效的问题第一反应应该是去看 Controller 和 Pilot 的日志确认配置到底卡在“转换”环节还是“推送”环节而不是直接去怀疑数据面。2. 一条请求进入 Higress 后到底发生了什么2.1 从 Listener 到 Filter Chain 的匹配逻辑当一个外部请求到达 Higress Gateway Pod 时首先命中的是 Envoy 的 Listener。Listener 就是端口监听器比如 80 和 443。每个 Listener 下面挂着一组 Filter Chain请求会按匹配条件通常是 SNI 域名和端口选中其中一条链。这条链上默认挂着几个关键 FilterHTTP Connection Manager负责把 TCP 连接解码成 HTTP 请求、CORS 过滤、故障注入过滤等。Higress 的自带插件比如限流、WAF也都是以 Envoy Filter 的形式插入到这条链中的。我重点说下匹配顺序域名和路径的匹配发生在 HTTP Connection Manager 内部它会根据 VirtualHost 和 Route 规则选择对应的 Cluster。所以多个域名共用同一个证书、多个路径前缀指向不同服务这些都是 Listener 层看不到的逻辑真正的决策在 RDS 层完成。2.2 路由规则背后的 VirtualService 模型Higress 对外的配置接口是 Ingress 或 HigressRoute CRD但对内的路由模型是 Istio 的 VirtualService。这意味着你在 Ingress 里写的 path 规则、header 匹配、权重分配最终都会被翻译成 VirtualService 里的 HTTPRoute。有个很容易踩的坑Ingress 的路径匹配规则和 VirtualService 的路径匹配规则并不完全一致。Ingress 的 pathType 分 Exact、Prefix 和 ImplementationSpecific而 VirtualService 主要是 prefix 和 exact。Higress Controller 在做转换时会把 Ingress 的 Prefix 映射成 VirtualService 的 prefix把 Exact 映射成 exact。但如果你直接用 HigressRoute CRD那走的是 VirtualService 原生的匹配规则能支持正则表达式。我建议复杂路由尽量用 CRD 而非 Ingress 注解理由后文会讲。2.3 Cluster 与负载均衡的执行细节请求匹配到 Route 后会被转发到对应的 Cluster。Cluster 定义了上游服务的连接方式、协议类型、负载均衡策略和熔断设置。Higress 会根据 Kubernetes Service 自动生成 Cluster这个过程相当于 EDS 的自动发现。负载均衡策略上Envoy 内置了 Round Robin、Least Request、Random 和 Maglev 等算法。Higress 默认用的是 Least Request因为它能更好地处理后端请求耗时不均的情况。如果你的服务实例处理能力差异大不要改回 Round RobinLeast Request 才是更贴近生产的选择。另外Envoy 在转发时会维持与上游的连接池。每个 worker 线程独立维护连接池长连接复用的效率很高。这里有个常见的性能瓶颈如果你后端服务对单 IP 的最大连接数有限制就会导致 Higress 的连接受拒绝。这时候需要调整的不是 Higress 的连接池而是后端服务的并发限制或者在 DestinationRule 里配置 outlierDetection 把异常实例踢掉。3. Higress 的核心功能到底靠什么原理实现3.1 插件机制为什么选择 WasmHigress 最有吸引力的特性之一就是它的插件体系是基于 WebAssemblyWasm的。普通用户可以用 Go 或 Rust 编写插件编译成 Wasm 文件后挂在网关上不需要改 Envoy 本体。这一点和常见网关用 Lua 脚本的方式有本质区别。Wasm 插件的执行环境是受限的沙箱内存安全、访问控制都有保障。即使插件 panic也不会把整个 Envoy 进程打挂。我在生产环境实际遇到过 Lua 脚本导致整个 OpenResty worker 崩溃的情况换成 Wasm 后这个问题彻底消失。插件加载路径分为 Wasm 运行时加载和 Envoy Filter 注入两个阶段。Higress 把 Wasm 插件抽象成了 CRD插件逻辑先被编译为 Wasm 二进制然后通过 Envoy 的 Wasm Filter 加载。这里注意一个插件就是一个 Filter插件之间可以通过 Filter 顺序控制执行先后。正则匹配、限流判断这些计算密集型的逻辑放在 Wasm 里执行性能比 Lua 要好不少。3.2 全局限流是怎么计算的限流是网关最常被问到的功能Higress 支持两种维度的限流网关级全局限流和基于路由的局部限流。全局限流的关键在于分布式计数数据不落在单节点而是通过 Redis 实现全局统计。我知道不少人觉得“限流就是发令牌”其实 Higress 的限流逻辑结合了固定窗口和滑动窗口的变体。默认场景下它按照配置的 time_window 和 threshold在 Redis 里维护一个滑动窗口计数。高并发下你对 Redis 的读写压力那才是真正的瓶颈所以线上建议给 Higress 的限流单独部署一个 Redis 实例不要和业务缓存共用否则一次业务缓存抖动就能影响网关限流的准确性。3.3 灰度发布与本地优先负载均衡的实现路径Higress 的灰度能力不止是简单的按权重分流。在 Istio 模型里它支持按 Header、Cookie、URI 前缀等条件将请求路由到不同版本这在 VirtualService 里就是多个 HTTPRoute 的匹配优先级问题。更值得一提的是本地优先负载均衡。在 Kubernetes 多可用区部署场景下如果 Pod 分布在多个节点池或可用区跨区调用会增加延迟。Higress 基于 Istio 的 Locality LB 能力优先把请求转发到同一可用区的后端实例。如果你遇到网关和业务 Pod 在同一个集群但延迟依然偏高的现象很可能是没启用 localityLbSetting。3.4 安全能力在数据面如何落地Higress 内置的安全插件包括 JWT 认证、Basic Auth、WAF 防护和 mTLS 通信。JWT 认证插件的执行位置在 HTTP Filter 层它会在请求进入路由匹配之前先校验 Token 签名和过期时间校验失败直接返回 401根本不会到业务后端。这样就减少了一层业务代码的健康检查压力。mTLS 方面Higress 控制面会自动下发 DestinationRule 里的 TLS 设置要求数据面与后端服务之间建立双向 TLS。很多人担心这个会带来额外性能损耗实测下来 CPU 占比上升非常有限但换来的是内部流量不会被明文嗅探尤其在等保合规要求严格的场景下很值。4. 选型对比Higress 与 Nginx Ingress、Kong、APISIX4.1 应用场景定位的差异选网关时第一个要搞清楚的问题是你要的是“Kubernetes Ingress Controller”还是“API 网关”。Nginx Ingress 的定位更偏前者它主要解决的是“把 Service 暴露到集群外部”的问题在路由、证书、灰度上都有能力但微服务级别的治理能力比如全局限流、跨服务鉴权相对薄弱。Kong 和 APISIX 则更像是传统的 API 网关它们以 Admin API 或 CRD 为配置入口插件体系成熟在 API 管理场景下用得很多。但它们和 Kubernetes 原生的 Ingress 模型融合度并不高通常需要额外的控制器把 Ingress 翻译成自己的路由模型。Higress 走的是中间路线原生支持 Ingress 和 Gateway API意味着你不用改变已有的 YAML 习惯同时又具备完整的 API 网关治理能力Wasm 插件把扩展门槛降到了 Go/Rust 开发者的舒适区内。我个人的选择标准很简单如果团队已经深度用 K8s且希望一套网关兼顾南北向入口和微服务治理Higress 是现在平衡度最高的选择。4.2 扩展机制的维度对比扩展机制是几个网关拉开差距最大的地方。Kong 基于 OpenResty插件主要用 Lua 编写。Lua 入门快但执行效率和内存安全不如编译型语言且插件写多了锁冲突和内存碎片会很明显。APISIX 也是 OpenResty 路线虽然引入了 WASM 支持但生态和成熟度还在补课阶段。Higress 直接以 Wasm 作为一等公民用 Go 写插件是官方主推的方式。Go 编译成 Wasm 后运行在 Envoy 沙箱里既安全又能复用 Go 的生态。团队里只要有人会 Go就能快速开发自定义插件不需要专门去学 Lua。这一点在招聘和技能复用上优势很明显。4.3 性能与运维成本的实测感受性能上Envoy 引擎没的说。但网关性能不能只看峰值 QPS更要看低负载时的延迟和 GC 停顿。Wasm 插件的调用有额外开销但 Higress 的插件执行在 Envoy 的工作线程内完成后开销是纳秒级到微秒级的差异不会成为瓶颈。运维层面Higress 和 K8s 的融合度高意味着可以用标准 Service、Pod、HPA 来管理网关实例日志直接走 stdout监控指标通过 Prometheus 暴露。不需要像 Nginx Ingress 那样去维护一堆配置文件模板也不需要像 Kong 那样单独管理一套数据库。这个“少一个组件”的收益长期看能省不少运维精力。我这里放一张简单对比表方便你收藏对比项HigressNginx IngressKongAPISIX底层引擎EnvoyNginxOpenRestyOpenRestyK8s 原生集成原生 Ingress / Gateway APIIngress需额外适配需额外适配插件语言Go / Rust / 多语言 WasmLua受限LuaLua / WASM配置存储K8s CRD无外部依赖K8sPostgreSQLetcd微服务治理能力强基于 Istio弱中中运维心智负担低低中中5. 实操部署与关键配置示例5.1 用 Helm 快速搭建一套 HigressHigress 的部署非常简单前提是你有一个健康可用的 Kubernetes 集群并且没有已经存在的 Istio 组件冲突。推荐用 Helm 方式安装命令大致如下helm repo add higress.io https://higress.io/helm-charts helm upgrade --install higress higress.io/higress \ --namespace higress-system \ --create-namespace \ --set global.ingressClasshigress安装完成后Higress 会默认创建一个名为 higress-gateway 的 Service类型是 LoadBalancer对外提供入口。你可以用kubectl get svc -n higress-system查看分配的 IP 或域名。这里有两个细节必须注意第一如果要使用 Gateway API需要额外安装 Gateway API 的 CRD第二默认安装会启用 Istio 的 sidecar 注入吗不会Higress 的 Pod 默认不启用 sidecar除非你明确设置。网关自身的高可用建议至少部署两个副本多可用区打散。5.2 从 Ingress 到 HigressRoute 的迁移样例如果你现在用的是 Nginx Ingress迁移到 Higress 时最稳妥的方式是先切 IngressClass让 Higress 接管流量。举个最简单的 Ingress 例子apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: demo-ingress namespace: default spec: ingressClassName: higress rules: - host: demo.example.com http: paths: - path: /api pathType: Prefix backend: service: name: demo-service port: number: 8080这段 YAML 和你写 Nginx Ingress 几乎一模一样只是把 ingressClassName 改成 higress。Higress 会自动翻译成内部路由。升级之后原本 Nginx Ingress 上的 annotation比如nginx.ingress.kubernetes.io/rewrite-target很多都不再生效需要改成 Higress 自己的注解格式。所以迁移前先检查所有 Ingress 上的注解清单这是最容易踩坑的环节。5.3 基于 HigressRoute CRD 的精细化路由Ingress 适合简单路由但碰到灰度发布或按请求头路由建议直接用 HigressRoute。下面的例子实现了按 header 路由到 canary 版本apiVersion: networking.higress.io/v1 kind: HigressRoute metadata: name: demo-route namespace: default spec: listeners: - port: 80 protocol: HTTP host: demo.example.com route: match: headers: version: exact: canary action: forward: serviceName: demo-service-canary port: 8080 --- apiVersion: networking.higress.io/v1 kind: HigressRoute metadata: name: demo-route-default namespace: default spec: listeners: - port: 80 protocol: HTTP host: demo.example.com route: match: prefix: / action: forward: serviceName: demo-service port: 8080这两条 CRD 放在同一命名空间、同一个 host 下Higress 会按顺序匹配第一条配置了 header 精确匹配优先级高于默认的 prefix 匹配。这是 Higress 路由里非常实用的技巧。5.4 性能调优的几个关键参数部署完只是开始生产环境你还得关注几个参数。Envoy 的--concurrency决定了 worker 线程数默认是 CPU 核数。大部分场景下不用动它但如果你的机器是 64 核而 QPS 并不高可以手动限制并发数降低上下文切换开销。连接池方面在 DestinationRule 里配置connectionPool.tcp.maxConnectionsPerHost和http.h2MaxStreams是非常值得做的。我建议小规格后端把单实例最大连接数调低一点避免某台机器被打爆。熔断配置里的outlierDetection也值得仔细设异常实例被剔除和恢复的时间直接关系到故障恢复速度。具体配置如下apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: demo-dr namespace: default spec: host: demo-service trafficPolicy: connectionPool: tcp: maxConnectionsPerHost: 100 http: h2MaxStreams: 100 outlierDetection: consecutive5xxErrors: 3 interval: 10s baseEjectionTime: 30s这套配置是我在标准 Web 服务上反复验证过的能有效防止慢实例拖垮整体延迟。6. 常见问题与排查技巧实录6.1 配置没生效先查链路别重启Higress 最常被吐槽的问题是“改了 Ingress 没生效”。排查思路我总结成固定步骤先看 Higress Controller 的日志有没有报错确认 Ingress 是否被成功转换为 VirtualService接着看 Pilot 的日志确认 xDS 推送是否正常最后看 Gateway Pod 的 Envoy 配置用istioctl proxy-config route检查 RDS 层是否已经有新的路由。大部分情况下问题出在第一步InressClass 没对上或者 Higress Controller 没有对应的集群权限。少部分情况是缓存延迟等几秒自动恢复不要一上来就重启 Pod。重启解决不了配置转换问题只会把排查窗口搞丢。6.2 后端服务不健康但网关仍在转发这个问题的根源通常是 Envoy 的异常检测默认参数太宽松或者 Cluster 配置里没有打开主动健康检查。Higress 默认基于异常检测做被动健康检查但需要连续出错多次才会被摘除。如果你的服务只是偶发抖动可以在 DestinationRule 里增加主动健康检查。主动健康检查的探测频率不能太高否则会放大后端服务压力。我一般用2s间隔、超时1s、健康判定阈值1、异常阈值3这样既灵敏又不会过度探测。6.3 Wasm 插件不生效的排查姿势插件不生效最常见的两个原因一是插件 CRD 里的matchRules配置有误没有匹配到具体路由二是插件对应的 Wasm 镜像无法拉取或者版本和 Higress 不兼容。拉取问题在离线或安全受限环境特别常见。建议提前把 Wasm 镜像拉下来推送到私有镜像仓库同时确保插件 CRD 的image字段指向正确地址。插件执行顺序如果不对也可能导致先执行的插件提前返回响应后面的插件没有机会运行。这时候要检查插件的phase配置我一般把逻辑归属为 UNIQUE 或 STATISTICS 阶段按实际需要调整。6.4 内存占用高的真实瓶颈有的团队反馈 Higress Gateway Pod 内存越用越高尤其是跑了多个 Wasm 插件后。这往往是 Wasm 插件实例数惹的祸。每个 worker 线程会创建插件实例如果插件里有大块缓存或全局状态内存就叠加了。解决办法是控制 worker 线程数减少插件实例数量。另一个隐藏因素是 Envoy 的统计指标数量Prometheus 拉取的指标越多内存越吃紧可以把不需要的统计项过滤掉。6.5 可观测性调优的一点心得Higress 默认暴露的 Prometheus 指标已经非常丰富包括请求量、延迟、错误率、上游连接状态等。但默认指标太多也会带来存储压力。我建议只保留核心指标比如envoy_http_downstream_rq_xx、envoy_cluster_upstream_rq_time、envoy_cluster_upstream_cx_active其他直接裁剪掉。日志方面Higress Gateway 的访问日志默认输出到 stdout格式是 Envoy JSON。可以用日志轮转方案把 stdout 接到日志平台再按域名和路径做统计分析。修改访问日志格式最好在 Helm values 里配置避免手动改 ConfigMap 后又被升级覆盖。7. 最后再分享一点实战体会我在多个集群上做过网关迁移从 Nginx Ingress 切到 Higress 的过程其实没有想象中痛苦。关键是在切流量前先把所有 Ingress 注解梳理一遍能翻译的就翻译不能翻译的优先改成 HigressRoute CRD。不要指望无缝迁移Higress 有自己的插件语义和路由模型把它当成一套新系统去规划反而会顺利很多。还有一个容易被忽略的点Higress 控制面依赖 Istio 模型意味着你团队里最好有人理解 VirtualService、DestinationRule 这些概念。不需要成为 Istio 专家但至少能看懂 xDS 的配置层级。当你排查复杂路由问题时这个知识储备能省下大量翻日志的时间。如果你正处在网关选型阶段我的建议是先跑一轮 POC把线上最复杂的几个路由场景灰度、多版本、限流、WAF完整迁移到 Higress压测看性能和错误率。POC 通过后再规划全量迁移。Higress 的社区和文档更新很活跃遇到问题优先在官方仓库的 issue 里搜索很多时候你踩过的坑别人已经填过土了。
阅读完成 · 觉得有帮助?
咨询建站