跳转到内容

数据面设计

数据面是 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 客户端是数据面在配置层面与外部世界的唯一连接。它实现了 ConfigurationDiscoveryService gRPC 服务的客户端侧。客户端:

  1. 连接到控制面的 gRPC 地址
  2. 发送 DiscoveryRequest,通过节点 ID(源自 Pod 名称或配置的标识符)标识自身
  3. 接收初始快照,作为包含完整 IR(以 protobuf 序列化)的 DiscoveryResponse
  4. 原子性地应用快照到代理运行时
  5. 确认 ACK(验证失败则为 NACK)
  6. 接收增量更新,作为同一流上后续的 DiscoveryResponse 消息
  7. 发送状态报告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 插件系统。

数据面是一个 Rust 工作空间,包含以下 crate:

Crate职责
ntgw-app数据面二进制入口,服务组装
ntgw-httpHTTP/gRPC 代理运行时和过滤器链
ntgw-aiAI 网关代理,多格式支持和限流
ntgw-wasmwasmtime 插件引擎和宿主函数
ntgw-streamTCP/UDP/TLS 流代理
ntgw-ir运行时 IR,快照索引和 protobuf 摄取
ntgw-xdsxDS 客户端,控制面配置流
ntgw-config数据面配置管理
ntgw-observability指标、追踪和可观测性基础设施
ntgw-allocator自定义内存分配器
ntgw-protoProtobuf 定义和生成代码
ntgw-shared-tls共享 TLS 配置和证书管理
ntgw-wasm-sdkWasm 插件开发 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 — 内存分配器

数据面通过 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 或请求头的会话亲和性

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 方法约束
客户端请求
|
v
TLS 终结(如果配置了 TLS)
|
v
路由匹配(主机名 + 路径 + 请求头)
|
v
过滤器链:请求头修改 -> CORS -> 限流 -> Wasm 插件 -> AI 转换
|
v
后端选择(负载均衡 + 会话保持)
|
v
后端连接(HTTP/1.1 或 HTTP/2 + TLS)
|
v
过滤器链:响应头修改 -> Wasm 插件
|
v
返回客户端

ntgw-stream 处理 L4 流量:TCP 和 UDP 连接。它在传输层运行,在客户端和后端之间转发字节,不检查应用层协议。

TCP 路由按监听器配置并按端口匹配。流代理接收监听器上的 TCP 连接,从配置的后端池中选择一个后端,并建立到后端的 TCP 连接。数据进行双向代理,直到任一方关闭连接。

UDP 路由工作方式类似,但处理面向数据报的流量。代理在监听器端口上绑定 UDP 套接字,接收数据报并转发到后端。UDP 会话跟踪确保来自同一源的相关数据报路由到同一后端。

后端被分组到池中,每个池代表 IR 中的一个 ServiceAIService。后端池管理:

数据面支持多种负载均衡算法,通过 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 网关功能都在代理进程内部完成,不需要额外的网络跳转。

ntgw-wasm 基于 wasmtime 提供了插件运行时。插件从 WasmPlugin CRD 加载,并在监听器或路由级别应用。

插件执行点:

  • HTTP 请求头:在路由前修改或检查请求头
  • HTTP 请求体:检查或转换请求体
  • HTTP 响应头:在客户端看到之前修改或检查响应头
  • HTTP 响应体:检查或转换响应体

插件在沙箱化的 WebAssembly 环境中运行,对主机资源的访问受限。它们通过定义良好的 ABI(应用程序二进制接口)与代理通信,提供请求头操作、请求体访问和日志记录等功能。

  • 生命周期钩子:在请求/响应处理的不同阶段注入自定义逻辑
  • 宿主函数:提供日志、HTTP 请求、配置读取等能力
  • 沙箱隔离:每个插件在独立的 Wasm 实例中运行
  • 热加载:通过 WasmPlugin CRD 更新插件配置,无需重启数据面

数据面使用 Rust 的 tracing 框架发出结构化日志,通过专用 HTTP 端点暴露 Prometheus 指标,以及可选的 OpenTelemetry 追踪。日志级别可按模块使用 tracing 过滤器指令进行配置(例如 info,hyper=warn 可在进行详细代理调试的同时避免 HTTP 库的噪音)。

指标端点暴露数据面专用的计数器,包括请求量、延迟直方图、后端健康状态、连接数和错误率。这些指标由 Prometheus 抓取,并在捆绑的 Grafana 仪表盘中可视化。

ntgw-observability 提供了完整的可观测性基础设施:

  • Prometheus 指标:请求速率、延迟、错误率、连接数、内存使用等
  • 结构化日志:基于 tracing crate 的分级日志
  • OpenTelemetry 集成:支持分布式追踪
  • Admin API:运行时诊断、配置查询和健康检查