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

semantic-router 多协议适配器架构:在 Envoy ExtProc 之外构建统一路由入口

semantic-router 多协议适配器架构:在 Envoy ExtProc 之外构建统一路由入口 ★ FEATURED ARTICLE
后端API网关模型推理服务AI Agent【免费下载链接】semantic-routerAn open, programmable decision layer for models and compute.项目地址https://gitcode.com/gh_mirrors/sem/semantic-router点击查看免费下载本文基于 vLLM Semantic Router 仓库中的设计提案《多协议适配器架构》撰写。Semantic Router 是一个开放、可编程的模型与算力决策层本文介绍其如何在保持现有 Envoy ExtProc 能力的同时通过薄适配器 单一 RouterEngine架构抽象出 HTTP、原生 gRPC、Nginx 等前端协议入口。读完本文你将掌握该多协议适配层的设计原则、组件划分、配置格式、初始化与并发模型以及如何新增一个协议适配器。概述vLLM Semantic Router 的 v0.3 设计文档描述了多协议适配器multi-protocol adaptor架构在 Envoy External ProcessorExtProc之外抽象出一层统一的 API 层使同一套路由引擎能够同时服务多种前端协议。核心思路是——路由逻辑与协议相关代码分离所有协议适配器都只是薄翻译层真正的分类、安全检测、缓存、工具选择、模型选择与重放记录全部收敛到唯一的RouterEngine.Route()入口中。从仓库现状看这一方向已经在持续推进英文原版提案website/docs/proposals/multi-protocol-adaptor.md已标记为Implemented已实现当前仓库中既保留了 Envoy ExtProc 的 gRPC 服务端src/semantic-router/pkg/extproc/server.go也存在着独立于 Envoy 的 HTTP/REST API 服务器src/semantic-router/pkg/apiserver并通过--gateway命令行参数在 standalone 与 extproc 两种网关模式间切换src/semantic-router/cmd/main.go。本文以下内容以设计提案为主体并结合这些仓库实现进行佐证与展开。背景为什么需要协议抽象Semantic Router 早期通过 gRPC 与 Envoy External ProcessorExtProc紧耦合。这种集成方式能深度利用 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()是唯一发生以下行为之处分类classificationPII / 越狱jailbreak检测缓存读 / 写工具选择重放replay记录后端选择代理或返回代理信息。架构总览提案给出的整体架构如下ASCII 图保留了原文的完整结构┌────────────────────────────────────────────────────────────┐ │ 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 中。这与英文原版提案中协议中立编解码矩阵Protocol-Neutral Codec Matrix的落地形态一致客户端线格式 → 入口编解码器ingress codec→ 中立请求 → 路由核心信号、决策、算法、插件→ Provider 编解码器 → 传输层 → 中立响应 → 客户端编解码器。组件设计1. RouterEngine核心规划位置pkg/router/engine/提案路径职责与协议无关的路由逻辑请求分类与决策求值语义缓存操作工具选择与嵌入路由器重放记录PII 与越狱检测模型选择。主要方法提案中的 Go 接口定义type RouterEngine struct { Config *config.RouterConfig Classifier *classification.Classifier PIIChecker *pii.PolicyChecker Cache cache.CacheBackend ToolsDatabase *tools.ToolsDatabase ModelSelector *selection.Registry ReplayRecorders map[string]*routerreplay.Recorder } func (e *RouterEngine) Route(ctx context.Context, req *RouteRequest) (*RouteResponse, error) func (e *RouterEngine) ClassifyRequest(ctx context.Context, messages []Message) (*ClassificationResult, error) func (e *RouterEngine) CheckCache(ctx context.Context, model, query, decisionName string) (string, bool, error) func (e *RouterEngine) UpdateCache(ctx context.Context, model, query, response, decisionName string) error func (e *RouterEngine) SelectTools(ctx context.Context, query string, topK int) ([]openai.ChatCompletionToolParam, error) func (e *RouterEngine) RecordReplay(ctx context.Context, decisionName string, record *routerreplay.RoutingRecord) error设计决策所有适配器共享单实例有状态维护缓存、重放记录器无协议专属逻辑返回与协议无关的数据结构。仓库佐证提案中ReplayRecorders map[string]*routerreplay.Recorder与仓库实现一一对应——src/semantic-router/pkg/routerreplay/recorder.go 定义了Recorder与RoutingRecord即store.Record并提供了DefaultMaxRecords 200、DefaultMaxBodyBytes 40964KB、DefaultOperationTimeout 5s等默认参数以及请求/响应体捕获策略SetCapturePolicy。重放记录是共享状态的一部分多适配器共享同一套记录器正是单一事实来源的具体体现。2. 适配器接口规划位置pkg/adapter/manager.go提案路径type Adapter interface { Start() error // Start the adapter (blocks) Stop() error // Graceful shutdown GetEngine() *engine.RouterEngine // Access to shared engine }设计决策接口最小化以保留灵活性各适配器自管生命周期接口中无协议专属方法适配器在独立 goroutine中运行。3. Adapter Manager规划位置pkg/adapter/manager.go提案路径职责解析适配器配置、按配置实例化、在独立 goroutine 中启动、协调优雅关闭。主要方法func (m *Manager) CreateAdapters(cfg *config.RouterConfig, eng *engine.RouterEngine, configPath string) error func (m *Manager) StartAll() error func (m *Manager) StopAll() error func (m *Manager) Wait()4. ExtProc 适配器规划位置pkg/adapter/extproc/提案路径包装现有 Envoy ExtProc 实现保持向后兼容处理 gRPC/Envoy 细节支持TLS。仓库佐证当前实现位于 src/semantic-router/pkg/extproc/server.go。Server结构体是一个面向 Envoy ExtProc 的 gRPC 服务端grpc.Server构造函数为NewServer(configPath, ...)它具备secure/certPath字段TLS 支持、内嵌 gRPC health 服务health.Server、configsnapshot.Manager配置快照管理以及config.GatewayMode网关模式字段。服务端还有默认生成排空超时defaultGenerationDrainTimeout 30s等生命周期参数可作为向后兼容、保持既有 ExtProc 能力的实现印证。5. HTTP 适配器规划位置pkg/adapter/http/提案路径提供OpenAI 兼容 REST API无需 Envoy处理 CORS、请求头等 HTTP 关注点。规划端点POST /v1/chat/completions核心对话补全POST /v1/completions未来GET /v1/modelsPOST /v1/classifyPOST /v1/routeGET /v1/router_replayGET /v1/router_replay/{id}GET /healthGET /ready仓库佐证当前仓库的 HTTP 侧实现位于 src/semantic-router/pkg/apiserver/routes_catalog.go其中的路由清单与提案端点高度重合并有所扩展例如/health健康检查、/ready就绪检查仅在启动完成后转绿、/startup-status启动与模型下载状态/openapi.jsonOpenAPI 3.0 规范、/docs交互式 Swagger UIGET /v1/modelsOpenAI 兼容的公开模型与 Entrypoint 列表/api/v1/classify/intent、/classify/pii、/classify/security、/classify/fact-check、/classify/combined、/classify/batch等分类诊断端点对应提案中的POST /v1/classify的细化落地/api/v1/routing/preview预览信号与模型选择对应提案中的POST /v1/route语义。API 根路径定义在 src/semantic-router/pkg/apiserver/api_paths.goapiRootPath /api/v1。这些端点都带权限与敏感度策略如PermHealthRead、SensitivityPublic说明 HTTP 面已经具备相当完整的工程化程度。6. gRPC 适配器规划位置pkg/adapter/grpc/提案路径提供原生 gRPC API相比 ExtProc 直连 gRPC 客户端更高效支持流式与一元 RPC。服务定义示例protobufservice SemanticRouter { rpc Route(RouteRequest) returns (RouteResponse); rpc Classify(ClassifyRequest) returns (ClassifyResponse); rpc StreamRoute(stream RouteRequest) returns (stream RouteResponse); }7. Nginx 适配器规划位置pkg/adapter/nginx/提案路径通过NJSJavaScript模块与 Nginx 集成支持OpenResty Lua基于头的路由方式类似 ExtProc。集成方式NJS 模块、Lua/OpenResty、HTTP 子请求内部调用 HTTP 适配器、共享内存 IPC。配置设计提案规定在单一配置文件中通过adapters节声明启用哪些协议适配器而非为每个适配器单独建配置文件或纯环境变量。完整示例adapters: - type: envoy # ExtProc adapter enabled: true port: 50051 tls: enabled: true cert_file: /path/to/cert.pem key_file: /path/to/key.pem - type: http # HTTP REST API enabled: true port: 9000 - type: grpc # Native gRPC API enabled: true port: 50052 tls: enabled: true cert_file: /path/to/cert.pem key_file: /path/to/key.pem - type: nginx # Nginx integration enabled: true port: 9001 mode: njs # Options: njs, lua, http config: upstream_variable: backend_upstream header_prefix: x-vsr-参数说明结合提案与仓库实现type适配器类型标识取值envoy/http/grpc/nginx对应 Adapter Manager 中的注册分支enabled是否启用该适配器可同时启用多个多协议并存port适配器监听端口各适配器互不冲突tls.enabled/cert_file/key_file是否启用 TLS 及证书路径。仓库中 ExtProc 服务端的secure/certPath字段pkg/extproc/server.go正是这一配置的落地载体modenginx集成模式njs/lua/http三选一config.upstream_variableNginx 中保存上游选择结果后端地址的变量名config.header_prefix路由器写入 Nginx 请求头的前缀如x-vsr-用于基于头的路由决策。数据流HTTP 适配器示例客户端请求 → 2. HTTP 适配器接收POST /v1/chat/completions→ 3. 解析 OpenAI 请求 → 4. 调用RouterEngine.Route→ 5. 分类、缓存、工具、重放等 → 6. 返回RouteResponse→ 7. 代理到选定后端 → 8. 返回客户端。共享状态多适配器共享同一缓存条目、重放记录器、分类决策与模型选择状态。这意味着无论请求从 ExtProc、HTTP 还是 gRPC 进入命中语义缓存、写入重放记录、分类结果都是一致的——这正是单一事实来源目标的实现路径。实现细节初始化顺序加载配置 → 2. 初始化嵌入模型 → 3. 创建 RouterEngine → 4. 创建 Adapter Manager → 5.CreateAdapters→ 6.StartAll→ 7.Wait()阻塞。迁移前ExtProc-only的启动方式是extproc.NewServer(...); server.Start()迁移后则统一为NewRouterEngine→adapter.NewManager→CreateAdapters→StartAll→Wait()并在config.yaml中增加adapters节。仓库佐证src/semantic-router/cmd/main.go 中通过--gateway参数解析网关模式config.ParseGatewayMode支持config.GatewayStandalone与config.GatewayExtProc两种模式并以extproc.WithGatewayMode(opts.gateway)传入 ExtProc 服务端。这说明standalone直连 HTTP为默认传输、--gateway extproc将同一路由核心挂接到 Envoy的迁移路径已在当前仓库落地与英文原版提案描述一致。错误处理适配器创建失败致命进程退出适配器启动失败致命进程退出运行时错误记录日志适配器在可能的情况下继续运行RouterEngine 错误返回适配器做协议相关处理例如把内部错误映射为 HTTP 状态码或 gRPC 错误码。并发模型RouterEngine线程安全多个适配器可并发调用Cache并发由后端处理Replay Recorders线程安全 map 按决策decision加锁Adapters独立 goroutine无共享适配器状态。仓库佐证src/semantic-router/pkg/routerreplay/recorder.go 中Recorder内含policyMu sync.RWMutex、recorderState内含lifecycleMu sync.Mutex与closeOnce sync.Once并用outcomeQueue异步结果队列承接记录落盘正对应线程安全 map 按决策加锁以及附录中重放建议异步写的设计建议。权衡与替代方案选用共享 RouterEngine 而非每适配器一实例理由跨协议决策一致共享缓存提高命中率重放记录单一来源内存占用更小。代价单实例可能成为热点通过线程安全设计缓解。适配器接口最小接口 vs 富接口选用最小接口Start/Stop/GetEngine而非包含HandleRequest、GetMetrics等的富接口。理由不同协议的请求/响应模型差异极大最小接口最灵活。配置单一配置文件中的adapters节而非每适配器独立文件或纯环境变量便于统一管理与版本化。已知局限抽象层难以做协议专属优化适配器之间不能直接通信有意设计若 RouterEngine 非线程安全共享状态存在竞态风险用户可配置项增多配置面变宽。测试策略单元测试RouterEngine 方法、各适配器逻辑、配置解析集成测试多适配器同时运行、跨适配器缓存一致性、双协议重放E2EEnvoy ExtProc8801与直连 HTTP9000验证相同的路由决策与重放可见性。仓库佐证英文原版提案将 E2E 覆盖进一步细化为 18 格矩阵3 个客户端协议 × 3 个原生后端协议 × 2 种模式每个单元都要穿越 Envoy 与 ExtProc、校验客户端原生缓冲信封或 SSE 生命周期、要求翻译输出中包含确定性后端标记、并拒绝泄漏的后端线格式。当前仓库中的协议编解码codec层与对应矩阵测试位于 src/semantic-router/pkg/protocolcodec可作为阅读协议中立层的入口。后续工作短期优雅关闭graceful shutdown适配器指标QPS、延迟直方图、错误率增强 Nginx 集成OpenResty、Nginx Plus、共享内存 IPC。长期gRPC 双向流WebSocket 适配器插件化动态加载适配器每适配器限流 / 认证 / 中间件。迁移指南以前ExtProc-onlyextproc.NewServer(...) server.Start()以后多协议NewRouterEngine → adapter.NewManager → CreateAdapters → StartAll → Wait()并在config.yaml中增加adapters节见上文配置设计。新增适配器步骤新建pkg/adapter/myprotocol/实现Adapter接口Start/Stop/GetEngine在manager.go中增加case myprotocol:注册分支增加对应的 YAML 配置。附录性能RouterEngine 单实例省内存但可能成为瓶颈缓存后端选型是关键重放建议异步写仓库中outcomeQueue即为异步落盘的实现适配器开销主要来自序列化协议编解码。安全每个适配器独立启用 TLS认证在适配器层处理未来可抽象外部鉴权PII / 越狱检测跨适配器共享保证所有入口安全策略一致。监控每适配器与 RouterEngine 各自暴露指标分布式追踪跨适配器 span 串联结构化日志每适配器健康检查端点对应仓库中/health、/ready等端点。参考本设计提案英文原版website/docs/proposals/multi-protocol-adaptor.md状态Implemented标题为 Protocol-Neutral Codec MatrixExtProc gRPC 服务端实现src/semantic-router/pkg/extproc/server.goHTTP REST API 路由清单src/semantic-router/pkg/apiserver/routes_catalog.go重放记录器实现src/semantic-router/pkg/routerreplay/recorder.go网关模式解析--gatewaysrc/semantic-router/cmd/main.go协议编解码层与矩阵测试src/semantic-router/pkg/protocolcodec赞分享后端API网关模型推理服务AI Agent【免费下载链接】semantic-routerAn open, programmable decision layer for models and compute.项目地址https://gitcode.com/gh_mirrors/sem/semantic-router点击查看免费下载相关推荐Semantic Router 的 Router API 参考基于 Envoy ExtProc 的 gRPC 路由接口、指标与集成实战Semantic Router 的 Router API 参考基于 Envoy ExtProc 的 gRPC 路由接口、指标与集成实战 Semantic Ro后端API网关模型推理服务AI Agentsemantic-router 基于 Istio Gateway 的 Kubernetes 部署实战ExtProc 智能路由接入semantic router 基于 Istio Gateway 的 Kubernetes 部署实战ExtProc 智能路由接入 本文是一份面向 vLLM S后端API网关模型推理服务AI Agentsemantic-router × NVIDIA Dynamo在 Kubernetes 上构建两层推理路由架构的完整实战semantic router × NVIDIA Dynamo在 Kubernetes 上构建两层推理路由架构的完整实战 本文基于 semantic rout后端API网关模型推理服务AI Agent创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站