设计文档:多协议适配器架构
作者: vLLM Semantic Router 团队
状态: 待实现
创建: 2026 年 2 月
最后更新: 2026 年 2 月
概述
本文描述 vLLM Semantic Router 的多协议适配器架构设计与实现思路,在 Envoy ExtProc 之外抽象 API 层,以支持多种前端协议。
背景
Semantic Router 曾通过 gRPC 与 Envoy External Processor(ExtProc)紧耦合。这虽能与 Envoy 深度集成,但对以下用户形成门槛:
- 希望在不部署 Envoy 的情况下使用路由器
- 偏好直接 HTTP/REST 集成
- 使用 Nginx 或其他反向代理
- 在开发或测试时需要更简化的部署拓扑
动机
- 灵活性:无需 Envoy 基础设施即可获得直连 HTTP API
- 测试:无需完整 Envoy 部署即可轻量测试
- 可扩展性:支持 nginx、原生 gRPC 与自定义协议
- 可复用性:所有协议共享同一路由引擎
- 部署形态:支持 serverless、边缘与简化部署
目标
主要目标
- 协议抽象:将路由逻辑与协议相关代码分离
- 多协议支持:允许多种协议同时工作
- 向后兼容:保留现有 ExtProc 能力
- 共享状态:缓存、重放与路由决策的单一事实来源
- 易于扩展:新增协议适配器的固定模式
非目标
- 替换或弃用 Envoy ExtProc
- 改变路由决策算法或分类逻辑
- 除适配器相关节外修改配置格式
- 支持破坏抽象层的协议专属特性
设计原则
1. 单一路由流水线
关键约束: 所有路由逻辑必须流经 RouterEngine.Route(),无一例外。
- 适配器将协议翻译为
RouteRequest→ 调用RouterEngine.Route() RouterEngine.Route()返回RouteResponse→ 适配器再翻译回协议- 适配器不得重复实现分类、安全、缓存、重放逻辑
- 适配器不得直接调用分类器、缓存或重放记录器
2. 薄适配器层
适配器仅做协议翻译:
- 解析协议专属请求格式
- 转换为
RouteRequest - 调用
RouterEngine.Route() - 将
RouteResponse转换为协议格式 - 返回给客户端
3. RouterEngine 拥有全部路由
RouterEngine.Route() 是唯一发生以下行为之处:
- 分类
- PII/越狱检测
- 缓存读/写
- 工具选择
- 重放记录
- 后端选择
- 代理(或返回代理信息)
设计
架构概览
┌────────────────────────────────────────────────────────────┐
│ Application Layer │
│ │
│ ┌───────────────────────────────────────────────────┐ │
│ │ Adapter Manager │ │
│ │ - Reads adapter config │ │
│ │ - Creates protocol adapters │ │
│ │ - Manages lifecycle │ │
│ └──────┬────────┬────────┬───────────┬──────────────┘ │
│ │ │ │ │ │
│ ┌──────▼──┐ ┌───▼─── ┐ ┌─▼──────┐ ┌──▼─────┐ │
│ │ ExtProc │ │ HTTP │ │ gRPC │ │ Nginx │ │
│ │ Adapter │ │Adapter │ │Adapter │ │Adapter │ │
│ │ ┌─────┐ │ │ ┌─────┐│ │ ┌─────┐│ │ ┌─────┐│ │
│ │ │Parse│ │ │ │Parse││ │ │Parse││ │ │Parse││ │
│ │ │ExtP │ │ │ │HTTP ││ │ │gRPC ││ │ │NJS ││ │
│ │ └──┬──┘ │ │ └─┬───┘│ │ └─┬───┘│ │ └──┬──┘│ │
│ │ │Conv│ │ │Con │ │ │Con │ │ │Con│ │
│ │ ▼ │ │ ▼ │ │ ▼ │ │ ▼ │ │
│ │ ┌─────┐ │ │ ┌────┐ │ │ ┌────┐ │ │ ┌─────┐│ │
│ │ │Req │ │ │ │Req │ │ │ │Req │ │ │ │Req ││ │
│ │ └──┬──┘ │ │ └─┬──┘ │ │ └─┬──┘ │ │ └──┬──┘│ │
│ └────┼────┘ └───┼────┘ └───┼────┘ └────┼───┘ │
│ │ │ │ │ │
│ └──────────┴──────────┴──────────┘ │
│ Single Entry Point │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────┐ │
│ │ RouterEngine.Route() │ │
│ │ 1. Classify request │ │
│ │ 2. Check PII / jailbreak │ │
│ │ 3. Check cache │ │
│ │ 4. Select tools │ │
│ │ 5. Select model/backend │ │
│ │ 6. Record replay │ │
│ │ 7. Proxy to backend (via Backend Layer) │ │
│ │ 8. Update cache │ │
│ └──────────────┬───────────────────────────┘ │
│ │ │
│ ▼ │
│ RouteResponse │
│ │ │
│ ┌──────────────┼──────────────┬───────────┐ │
│ │ │ │ │ │
│ ┌─────▼─────┐ ┌──────▼────┐ ┌───────▼───┐ ┌─────▼─────┐ │
│ │ ExtProc │ │ HTTP │ │ gRPC │ │ Nginx │ │
│ │ Adapter │ │ Adapter │ │ Adapter │ │ Adapter │ │
│ │ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │ │
│ │ │Convert│ │ │ │Convert│ │ │ │Convert│ │ │ │Convert│ │ │
│ │ │to gRPC│ │ │ │to HTTP│ │ │ │gRPC │ │ │ │to NJS │ │ │
│ │ └───────┘ │ │ └───────┘ │ │ └───────┘ │ │ └───────┘ │ │
│ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ │
│ │ │ │ │ │
└────────┼─────────────┼─────────────┼─────────────┼─────────┘
│ │ │ │
└─────────────┴─────────────┴─────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Backend Abstraction Layer │
└──────┬──────────────────┬───────────────┘
│ │
┌────────▼────────┐ ┌──────▼──────────┐
│ Envoy Proxy │ │ Direct Proxy │
│ (ExtProc mode) │ │ (HTTP/gRPC) │
│ - Dynamic fwd │ │ - HTTP client │
│ - Headers only │ │ - Full response │
└────────┬────────┘ └──────┬──────────┘
│ │
└──────────┬───────┘
▼
┌───────────────────── ───────┐
│ Inference Backends │
│ ┌────────┐ ┌────────┐ │
│ │ vLLM │ │Ollama │ │
│ │Server │ │Server │ │
│ └────────┘ └────────┘ │
└────────────────────────────┘
要点: 适配器是薄翻译层,智能全部在 RouterEngine。
组件设计
1. RouterEngine(核心)
位置: pkg/router/engine/
职责:
- 与协议无关的路由逻辑
- 请求分类与决策求值
- 语义缓存操作
- 工具选择与嵌入
- 路由器重放记录
- PII 与越狱检测