数据面设计
数据面是 Nantian Gateway 的执行引擎。它是一个用 Rust 编写的高性能代理,通过 gRPC/xDS 从控制面接收配置,将其应用到代理运行时,处理所有南北向流量。它以独立二进制形式运行,连接控制面下载配置后即可独立运作。
数据面围绕一个代理核心构建,该核心将 xDS 配置应用到 HTTP 和 TCP/UDP 代理栈。xDS 客户端维护与控制面的持久双向 gRPC 流。当新配置快照到达时,客户端反序列化 protobuf,验证并将其原子性地应用到代理运行时。
+-----------------------------+| Rust 数据面 || || +-----------------------+ || | xDS 客户端 | | 到控制面的 gRPC 流| | - 连接管理 | | 控制面地址(默认::18080)| | - Proto 反序列化 | || | - 快照验证 | || +-----------+------------+ || | || v || +-----------+------------+ || | 代理运行时 | || | | || | +--------+ +--------+ | || | | HTTP | | 流代理 | | || | | 代理 | | | | || | +----+---+ +----+---+ | || | | | | || | +----v----------v--+ | || | | 后端池 | | || | | - 负载均衡 | | || | | - 健康检查 | | || | | - 熔断 | | || | +-------------------+ | || +---------------------------+ || | || +-----------v------------+ || | Wasm 运行时 | | 可选的 WebAssembly 扩展| | - 插件加载 | || | - 请求/响应 | || +------------------------+ |+-----------------------------+xDS 客户端
Section titled “xDS 客户端”xDS 客户端是数据面在配置层面与外部世界的唯一连接。它实现了 ConfigurationDiscoveryService gRPC 服务的客户端侧。客户端:
- 连接到控制面的 gRPC 地址
- 发送
DiscoveryRequest,通过节点 ID(源自 Pod 名称或配置的标识符)标识自身 - 接收初始快照,作为包含完整 IR(以 protobuf 序列化)的
DiscoveryResponse - 原子性地应用快照到代理运行时
- 确认 ACK(验证失败则为 NACK)
- 接收增量更新,作为同一流上后续的
DiscoveryResponse消息 - 发送状态报告(
DataplaneStatusReport)回控制面,包括代理健康状态、活跃监听器、路由计数和后端连接性
客户端透明地处理重连。如果 gRPC 流中断,客户端以指数退避重试。重连期间,代理继续使用上次已知配置处理流量。
IDLE --> CONNECTING --> HANDSHAKE --> ACTIVE ^ | | | +-------- DISCONNECTED <-------------------+- IDLE:初始状态,未尝试连接
- CONNECTING:到控制面的 TCP 连接进行中
- HANDSHAKE:gRPC 流握手,节点注册
- ACTIVE:流已建立,接收配置
- DISCONNECTED:流中断,重试计时器运行
数据面基于 Pingora 框架构建。Pingora 是 Cloudflare 开源的 Rust 异步代理框架,提供了 HTTP/1 和 HTTP/2 代理、连接池、健康检查、TLS 支持和可观测性等基础设施。Nantian Gateway 在此基础上扩展了 Gateway API 路由、流代理、AI 网关和 Wasm 插件系统。
Crate 结构
Section titled “Crate 结构”数据面是一个 Rust 工作空间,包含以下 crate:
| Crate | 职责 |
|---|---|
ntgw-app | 数据面二进制入口,服务组装 |
ntgw-http | HTTP/gRPC 代理运行时和过滤器链 |
ntgw-ai | AI 网关代理,多格式支持和限流 |
ntgw-wasm | wasmtime 插件引擎和宿主函数 |
ntgw-stream | TCP/UDP/TLS 流代理 |
ntgw-ir | 运行时 IR,快照索引和 protobuf 摄取 |
ntgw-xds | xDS 客户端,控制面配置流 |
ntgw-config | 数据面配置管理 |
ntgw-observability | 指标、追踪和可观测性基础设施 |
ntgw-allocator | 自定义内存分配器 |
ntgw-proto | Protobuf 定义和生成代码 |
ntgw-shared-tls | 共享 TLS 配置和证书管理 |
ntgw-wasm-sdk | Wasm 插件开发 SDK |
ntgw-app(二进制入口)├── ntgw-config — YAML 配置,文件监听├── ntgw-http — HTTP/gRPC 代理(基于 Pingora),过滤器、会话、缓存│ ├── ntgw-ai — AI 网关代理(限流、多格式协议转换)│ ├── ntgw-wasm — wasmtime 插件引擎│ │ └── ntgw-wasm-sdk│ ├── ntgw-ir — 运行时 IR,路由匹配、负载均衡、快速路径│ │ └── ntgw-proto — Protobuf 代码生成│ └── ntgw-observability — 指标、追踪、OTel├── ntgw-stream — TCP/UDP/TLS 流代理├── ntgw-xds — xDS 客户端└── ntgw-allocator — 内存分配器配置接收与 IR 摄取
Section titled “配置接收与 IR 摄取”数据面通过 xDS 协议从控制面接收配置。流程如下:
控制面 gRPC xDS Server | | gRPC 双向流(protobuf) | +----v-------------------+
| ntgw-xds | xDS 客户端 | 订阅配置,解析 protobuf | +----+-------------------+ | | IR protobuf | +----v-------------------+
| ntgw-ir | 运行时 IR | 构建路由索引,快照管理 | +----+-------------------+ | | 路由表 + 后端 + 策略 | +----v-------------------+
| ntgw-http / ntgw-stream | 代理运行时 | 应用配置,处理流量 | +------------------------+ntgw-ir 是数据面的核心。它接收控制面推送的 protobuf 格式 IR,构建高性能的内存索引,包括:
- 路由匹配索引:按主机名、路径前缀、请求头等维度建立快速查找表
- 后端集群索引:按名称索引后端服务及其端点列表
- 负载均衡策略:支持轮询、最少连接、随机、一致性哈希等算法
- 会话保持:基于 Cookie 或请求头的会话亲和性
HTTP 代理
Section titled “HTTP 代理”ntgw-http 实现了一个完整的 HTTP 代理,基于 Pingora 的代理框架:
- HTTP/1.1 和 HTTP/2:支持明文(h2c)和 TLS 加密的 HTTP/2
- gRPC:原生 gRPC 代理,支持命名路由规则
- WebSocket:透明代理 WebSocket 连接
- TLS 终结:支持 SNI、mTLS 和多种 TLS 版本。每个监听器可以配置一个或多个 TLS 证书,引用自 Kubernetes Secret。代理支持:服务端 TLS(使用服务器证书终止客户端连接)、双向 mTLS(要求客户端证书进行认证)、后端 TLS(通过 BackendTLSPolicy 配置向源后端发起 TLS 连接)以及基于 SNI 的路由(根据客户端的 Server Name Indication 选择证书)。IR 中的证书支持热加载:当 Kubernetes Secret 变更时,新证书出现在下一个 IR 快照中,数据面无需重启即可将其应用到运行中的监听器。
- 过滤器链:请求/响应生命周期中的可插拔过滤器。HTTP 代理对每个请求应用过滤器链。过滤器可以在请求到达后端之前修改请求,以及在响应到达客户端之前修改响应:请求头修改(添加、设置或删除 HTTP 请求头)、响应头修改(添加、设置或删除 HTTP 响应头)、请求重定向(直接从代理返回 HTTP 重定向)、URL 重写(在转发前修改请求路径或主机名)、限流(强制执行每路由或每后端的速率限制)以及 Wasm 插件(执行可以检查和修改请求/响应的自定义 WebAssembly 模块)
路由按监听器配置。每个监听器绑定到一个地址和端口,路由按优先级顺序评估。第一个匹配的路由胜出。路由匹配支持:
- 路径匹配:精确、前缀和正则表达式
- 请求头匹配:精确和正则表达式匹配请求头值
- 查询参数匹配:精确和正则表达式匹配查询值
- 方法匹配:HTTP 方法约束
请求处理流程
Section titled “请求处理流程”客户端请求 | vTLS 终结(如果配置了 TLS) | v路由匹配(主机名 + 路径 + 请求头) | v过滤器链:请求头修改 -> CORS -> 限流 -> Wasm 插件 -> AI 转换 | v后端选择(负载均衡 + 会话保持) | v后端连接(HTTP/1.1 或 HTTP/2 + TLS) | v过滤器链:响应头修改 -> Wasm 插件 | v返回客户端ntgw-stream 处理 L4 流量:TCP 和 UDP 连接。它在传输层运行,在客户端和后端之间转发字节,不检查应用层协议。
TCP 代理
Section titled “TCP 代理”TCP 路由按监听器配置并按端口匹配。流代理接收监听器上的 TCP 连接,从配置的后端池中选择一个后端,并建立到后端的 TCP 连接。数据进行双向代理,直到任一方关闭连接。
UDP 代理
Section titled “UDP 代理”UDP 路由工作方式类似,但处理面向数据报的流量。代理在监听器端口上绑定 UDP 套接字,接收数据报并转发到后端。UDP 会话跟踪确保来自同一源的相关数据报路由到同一后端。
后端被分组到池中,每个池代表 IR 中的一个 Service 或 AIService。后端池管理:
数据面支持多种负载均衡算法,通过 BackendLBPolicy 配置:
- 轮询:将请求均匀分配到健康后端
- 最少连接:将请求发送到活跃连接数最少的后端
- 随机:根据端点权重随机选择后端
- 一致性哈希:对请求属性(源 IP、请求头、Cookie)进行哈希处理,以一致地路由到同一后端
会话保持通过 BackendLBPolicy 配置,确保来自同一客户端的请求在可配置的持续时间内路由到同一后端。代理使用基于 Cookie 或请求头的亲和性。
后端通过主动和被动健康检查进行监控:
- 主动健康检查:代理定期向后端发送 HTTP 或 TCP 探针。不健康的后端会暂时从池中移除。
- 被动健康检查:代理跟踪连接和请求失败。当失败次数超过阈值时,后端被标记为不健康。
熔断器保护后端服务免受过载。每个后端池可以配置最大连接数限制、最大待处理请求数和每连接限制。当熔断器打开时,代理以 503 Service Unavailable 响应拒绝请求,而不是将其转发到过载的后端。
ntgw-ai 是数据面内置的 AI 网关模块,处理多 AI 提供方的协议适配:
- 多格式支持:OpenAI、Anthropic 和 Ollama 三种 API 格式
- Token 管理:实时 token 计数、配额控制和限流
- API 密钥管理:密钥验证、轮换和提供方路由
- PII 脱敏:在请求和响应中检测和脱敏敏感信息
- 模型 A/B 测试:按比例将请求分流到不同模型版本
所有 AI 网关功能都在代理进程内部完成,不需要额外的网络跳转。
Wasm 插件系统
Section titled “Wasm 插件系统”ntgw-wasm 基于 wasmtime 提供了插件运行时。插件从 WasmPlugin CRD 加载,并在监听器或路由级别应用。
插件执行点:
- HTTP 请求头:在路由前修改或检查请求头
- HTTP 请求体:检查或转换请求体
- HTTP 响应头:在客户端看到之前修改或检查响应头
- HTTP 响应体:检查或转换响应体
插件在沙箱化的 WebAssembly 环境中运行,对主机资源的访问受限。它们通过定义良好的 ABI(应用程序二进制接口)与代理通信,提供请求头操作、请求体访问和日志记录等功能。
- 生命周期钩子:在请求/响应处理的不同阶段注入自定义逻辑
- 宿主函数:提供日志、HTTP 请求、配置读取等能力
- 沙箱隔离:每个插件在独立的 Wasm 实例中运行
- 热加载:通过
WasmPluginCRD 更新插件配置,无需重启数据面
数据面使用 Rust 的 tracing 框架发出结构化日志,通过专用 HTTP 端点暴露 Prometheus 指标,以及可选的 OpenTelemetry 追踪。日志级别可按模块使用 tracing 过滤器指令进行配置(例如 info,hyper=warn 可在进行详细代理调试的同时避免 HTTP 库的噪音)。
指标端点暴露数据面专用的计数器,包括请求量、延迟直方图、后端健康状态、连接数和错误率。这些指标由 Prometheus 抓取,并在捆绑的 Grafana 仪表盘中可视化。
ntgw-observability 提供了完整的可观测性基础设施:
- Prometheus 指标:请求速率、延迟、错误率、连接数、内存使用等
- 结构化日志:基于 tracing crate 的分级日志
- OpenTelemetry 集成:支持分布式追踪
- Admin API:运行时诊断、配置查询和健康检查