news 2026/9/18 5:20:47

AIBrix 多引擎(Multi-Engine)支持实战指南:一套集群统一调度 vLLM、SGLang、xLLM 与 TRT-LLM

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AIBrix 多引擎(Multi-Engine)支持实战指南:一套集群统一调度 vLLM、SGLang、xLLM 与 TRT-LLM

AIBrix 多引擎(Multi-Engine)支持实战指南:一套集群统一调度 vLLM、SGLang、xLLM 与 TRT-LLM

【免费下载链接】aibrixCost-efficient and pluggable Infrastructure components for GenAI inference项目地址: https://gitcode.com/GitHub_Trending/ai/aibrix

本文围绕 AIBrix 的多引擎调度(Multi-Engine Scheduling)能力展开,介绍如何在同一套 AIBrix 实例下同时部署 vLLM、SGLang、xLLM、TRT-LLM 等多种推理引擎,通过 Pod 标签(label)完成引擎识别与指标适配,并让路由策略(Router)基于各引擎真实导出的 Prometheus 指标做请求分发。读完本文,你将掌握model.aibrix.ai/engine系列标签的完整配置方法、跨引擎指标映射原理、TRT-LLM 的接入要点,以及如何为 AIBrix 扩展新的引擎类型。

为什么需要多引擎支持

在引入多引擎能力之前,AIBrix 在模型服务阶段只支持 vLLM 单一引擎。这带来的直接限制是:在同一个工作负载或基准测试(benchmarking)场景中,无法灵活地在不同引擎之间进行实验与对比。

多引擎支持为 AIBrix 带来了三方面价值:

  • 并排对比(Side-by-side comparisons):在同一套集群中横向对比不同引擎的端到端延迟、吞吐与行为特征,为引擎选型提供一手数据;
  • 部署灵活性(Deployment flexibility):支持模型分片(model sharding)或迁移策略,例如将部分流量导向 SGLang、部分导向 TRT-LLM;
  • 指标适配(Metrics Adaptation):不同引擎导出的 Prometheus 指标名不同,AIBrix 通过统一的抽象指标名 + 引擎映射表来正确解读每种引擎的指标。

系统工作方式:标签驱动 + 指标映射

多引擎调度的核心设计是标签驱动:入站请求会借助 Deployment 上的标签,决定如何解读从 Prometheus API 拉取到的指标,而这些指标随后被 Router 用于请求委派(delegate execution)。

配置某个引擎时,只需在 Deployment 的 Pod 模板(template)上添加如下标签:

labels: model.aibrix.ai/name: deepseek-llm-7b-chat model.aibrix.ai/engine: "sglang" model.aibrix.ai/metric-port: "8000" # 当 Prometheus 端口与默认端口不同时配置 model.aibrix.ai/port: "8000"

AIBrix 使用model.aibrix.ai/engine标签确定该 Deployment 使用哪个引擎,并据此在所有从 Prometheus 拉取的指标中查找正确的指标名格式。

目前支持的引擎标签取值为:vllmsglangxllmtrtllm

完整工作流程(三步)

  1. Pod 监听与引擎识别:AIBrix 缓存(cache)监听携带model.aibrix.ai/name标签的 Pod,并从同一 Pod 上读取model.aibrix.ai/engine。AIBrix 内部使用的每一个指标都有一个抽象名称(例如num_requests_waiting),并对应一张“引擎 → 引擎实际导出的指标名”的映射表,该映射定义在 pkg/metrics/metrics.go 中(完整映射见下文"跨引擎指标映射表"一节)。
  2. 指标抓取:指标从每个 Pod 的model.aibrix.ai/metric-port端口(缺省为8000)的/metrics路径抓取;对于trtllm引擎,路径为/prometheus/metrics。请求则被转发到model.aibrix.ai/port端口。
  3. 路由策略取值与降级:路由策略向缓存请求抽象指标名。当某个引擎没有提供策略所需的指标映射时,大多数策略(least-requestleast-kv-cacheleast-latencyleast-busy-timeleast-gpu-cacheleast-utilthroughput)会为该请求回退到随机 Pod;而 SLO 系列策略(slo-least-loadslo-pack-loadslo-least-load-pulling)则直接返回错误,该错误会以 HTTP 503 的形式呈现给客户端。

说明:可选的 runtime sidecar 是一套独立的机制,它会在自己的端口上以标准化形态重新导出引擎指标;引擎标签的使用并不依赖该 sidecar。

从源码看实现细节

在 pkg/cache/cache_metrics.go 中可以看到完整的数据通路:

  • 常量MetricPortLabel = constants.ModelLabelMetricPortengineLabel = constants.ModelLabelEnginedefaultMetricPort = 8000defaultEngineLabelValue = "vllm"(pkg/cache/cache_metrics.go)定义了标签与默认值;
  • getPodMetricPort解析 Pod 的model.aibrix.ai/metric-port标签,解析失败或缺失时回退到默认端口8000(pkg/cache/utils.go);
  • 指标抓取工作线程workerpod.Status.PodIP:podMetricPort作为 endpoint,调用metrics.GetEngineType(*pod.Pod)获取引擎类型,再经FetchAllTypedMetrics统一抓取所有类型化指标(pkg/cache/cache_metrics.go);
  • 引擎指标路径由 pkg/metrics/engine_fetcher.go 的metricsPathForEngine决定:trtllm使用prometheus/metrics,其余引擎统一使用metrics
  • 当引擎指标自带engine_type/model_name标签缺失或为undefined时,sanitizeMetricLabels会使用 Pod 标签(model.aibrix.ai/enginemodel.aibrix.ai/name)回填,保证指标归属正确(pkg/cache/cache_metrics.go)。

所有标签键在 pkg/constants/model.go 中以常量形式统一声明:ModelLabelNameModelLabelEngineModelLabelMetricPortModelLabelPort(pkg/constants/model.go),格式遵循resource.aibrix.ai/attribute约定。

配置参考:四个核心标签

多引擎的一切配置都通过 Pod 标签完成。注意:请将这些标签设置在Deployment的 Pod 模板(pod template)上(如果是 StormService,则设置在 role 上),而不是设置在 workload 对象(如 Deployment 本身)的 metadata 上——这与 samples/quickstart/tensorrt/tensor-rt.yaml 中的写法一致:Deployment 顶层metadata.labels只放app与模型名,model.aibrix.ai/engine放在spec.template.metadata.labels

标签默认值含义
model.aibrix.ai/name必填请求中使用的模型名,同时用于 Pod 发现。
model.aibrix.ai/enginevllm引擎类型,取值为vllmsglangxllmtrtllm之一,决定选用哪张指标映射表。
model.aibrix.ai/port8000引擎对外提供推理服务的端口。
model.aibrix.ai/metric-port8000引擎暴露/metrics的端口;当指标端口与推理服务端口不同时配置(例如引擎与 HTTP 代理分离部署的场景,见 pkg/cache/cache_metrics.go 的注释)。

跨引擎指标映射表(Supported Metrics)

AIBrix 目前只支持各引擎有限数量的指标,且会持续扩充。对于通过 routing policy API 实现的路由算法(位于 pkg/plugins/gateway/algorithms),请确保使用的指标在你的目标引擎上受支持。如上文"工作流程"所述,大多数现有路由策略在无法获取目标指标时会回退到默认(随机)策略,SLO 系列策略除外。

下表完整列出了 AIBrix 抽象指标名到各引擎实际导出指标名的映射(N/A 表示该引擎不提供此指标):

AIBrix 指标vLLMSGLangxLLMTRT-LLM
num_requests_runningvllm:num_requests_runningsglang:num_running_reqsN/AN/A
num_requests_waitingvllm:num_requests_waitingsglang:num_queue_reqsN/AN/A
num_requests_swappedvllm:num_requests_swappedsglang:num_retracted_reqsN/AN/A
engine_sleep_statevllm:engine_sleep_stateN/AN/AN/A
http_requests_totalvllm:http_requests_totalN/AN/AN/A
num_preemptions_totalvllm:num_preemptions_totalN/AN/AN/A
request_success_totalvllm:num_requests_success_totalsglang:num_requests_totalN/Atrtllm_request_success_total
num_prefill_prealloc_queue_reqsN/Asglang:num_prefill_prealloc_queue_reqsN/AN/A
num_decode_prealloc_queue_reqsN/Asglang:num_decode_prealloc_queue_reqsN/AN/A
e2e_request_latency_secondsvllm:e2e_request_latency_secondssglang:e2e_request_latency_secondsN/Atrtllm_e2e_request_latency_seconds
request_queue_time_secondsvllm:request_queue_time_secondsN/AN/Atrtllm_request_queue_time_seconds
request_inference_time_secondsvllm:request_inference_time_secondsN/AN/AN/A
per_stage_req_latency_secondsN/Asglang:per_stage_req_latency_secondsN/AN/A
http_request_duration_secondshttp_request_duration_secondsN/AN/AN/A
http_request_duration_highr_secondshttp_request_duration_highr_secondsN/AN/AN/A
prompt_tokens_totalvllm:prompt_tokens_totalN/AN/AN/A
request_prompt_tokensvllm:request_prompt_tokensN/AN/AN/A
generation_tokens_totalvllm:generation_tokens_totalN/AN/AN/A
request_generation_tokensvllm:request_generation_tokensN/AN/AN/A
request_max_num_generation_tokensvllm:request_max_num_generation_tokensN/AN/AN/A
iteration_tokens_totalvllm:iteration_tokens_totalN/AN/AN/A
time_to_first_token_secondsvllm:time_to_first_token_secondssglang:time_to_first_token_secondsN/Atrtllm_time_to_first_token_seconds
time_per_output_token_secondsvllm:time_per_output_token_secondssglang:inter_token_latency_secondsN/Atrtllm_time_per_output_token_seconds
inter_token_latency_secondsvllm:inter_token_latency_secondssglang:inter_token_latency_secondsN/Atrtllm_time_per_output_token_seconds
request_decode_time_secondsvllm:request_decode_time_secondsN/AN/AN/A
request_prefill_time_secondsvllm:request_prefill_time_secondsN/AN/AN/A
request_time_per_output_token_secondsvllm:request_time_per_output_token_secondsN/AN/AN/A
gpu_cache_usage_percvllm:gpu_cache_usage_percsglang:token_usagekv_cache_utilizationN/A
engine_utilizationN/AN/Aengine_utilizationN/A
cpu_cache_usage_percvllm:cpu_cache_usage_percN/AN/AN/A
kv_cache_usage_percvllm:kv_cache_usage_percsglang:token_usagekv_cache_utilizationtrtllm_kv_cache_utilization
kv_cache_hit_rateN/AN/AN/Atrtllm_kv_cache_hit_rate
prefix_cache_queries_totalvllm:prefix_cache_queries_totalN/AN/AN/A
prefix_cache_hits_totalvllm:prefix_cache_hits_totalN/AN/AN/A
external_prefix_cache_queries_totalvllm:external_prefix_cache_queries_totalN/AN/AN/A
external_prefix_cache_hits_totalvllm:external_prefix_cache_hits_totalN/AN/AN/A
nixl_xfer_time_secondsvllm:nixl_xfer_time_secondsN/AN/AN/A
nixl_post_time_secondsvllm:nixl_post_time_secondsN/AN/AN/A
nixl_bytes_transferredvllm:nixl_bytes_transferredN/AN/AN/A
nixl_num_descriptorsvllm:nixl_num_descriptorsN/AN/AN/A
nixl_num_failed_transfers_totalvllm:nixl_num_failed_transfersN/AN/AN/A
nixl_num_failed_notifications_totalvllm:nixl_num_failed_notificationsN/AN/AN/A
avg_prompt_throughput_toks_per_svllm:avg_prompt_throughput_toks_per_sN/AN/AN/A
avg_generation_throughput_toks_per_svllm:avg_generation_throughput_toks_per_ssglang:gen_throughputN/AN/A
max_loravllm:lora_requests_infoN/AN/AN/A
running_lora_adaptersvllm:lora_requests_infoN/AN/AN/A
waiting_lora_adaptersvllm:lora_requests_infoN/AN/AN/A

补充说明两点:

  • SGLang 的gpu_cache_usage_perckv_cache_usage_perc均映射到sglang:token_usage,这一点在 pkg/metrics/metrics.go 与 pkg/metrics/metrics.go 的源码注释中也有明确标注(// Based on ...)。
  • time_per_output_token_seconds在 AIBrix 内部已被标记为 deprecated,推荐使用inter_token_latency_seconds替代(见 pkg/metrics/metrics.go 的注释),但两者的引擎映射均被保留以兼容现有策略。

指标的类型化抓取

从源码看,AIBrix 将指标分为三类分别抓取(pkg/cache/cache_metrics.go):

  • counter/gauge 类counterGaugeMetricNames):如num_requests_runningkv_cache_usage_perc等,直接读取原始值;
  • histogram 类histogramMetricNames):如time_to_first_token_secondse2e_request_latency_seconds等,涉及_sum/_bucket/_count序列;
  • PromQL 查询类prometheusMetricNames):如P95TTFT5mAvgRequestsPerMinPod等,需要在 pkg/metrics/metrics.go 中预定义 PromQL 模板,再由缓存按instancemodel_name标签实时查询。

需要留意的是,部分 PromQL 查询类指标(例如P95TTFT5m)的模板目前仍硬编码引用vllm:前缀的指标名,源码中以// TODO: make it agnostic to the engine(pkg/metrics/metrics.go)标注了待办——也就是说,原始指标(raw metric)已完全引擎无关化,但少量查询类指标的引擎无关化仍在推进中

TRT-LLM 快速上手

将 TRT-LLM 作为推理引擎时,在 Deployment 上设置model.aibrix.ai/engine: trtllm标签即可。TRT-LLM 必须在服务端配置中显式开启性能指标暴露:return_perf_metrics: trueenable_iter_perf_stats: trueenable_iter_req_stats: true

官方示例配置位于:

  • samples/quickstart/tensorrt/tensor-rt.yaml — 标准单实例部署;
  • samples/quickstart/tensorrt/tensor-rt-pd.yaml — 基于 StormService 的 prefill/decode 分离部署。

TRT-LLM 的部署标签配置示例:

labels: model.aibrix.ai/name: Qwen3-8B model.aibrix.ai/engine: trtllm model.aibrix.ai/port: "8000"

参考 samples/quickstart/tensorrt/tensor-rt.yaml 的完整写法,一个可运行的 TRT-LLM Deployment 形如:

apiVersion: apps/v1 kind: Deployment metadata: name: qwen-tensorrt-llm labels: app: qwen-llm model.aibrix.ai/name: Qwen3-8B model.aibrix.ai/port: "8000" spec: replicas: 1 selector: matchLabels: app: qwen-llm template: metadata: labels: app: qwen-llm model.aibrix.ai/name: Qwen3-8B model.aibrix.ai/port: "8000" model.aibrix.ai/engine: trtllm spec: containers: - name: tensorrt-llm image: <tensorrt-llm 镜像> command: ["/bin/bash", "-c"] args: - | cat <<'EOF' > /tmp/config.yaml backend: pytorch kv_cache_config: free_gpu_memory_fraction: 0.85 max_num_tokens: 8192 max_batch_size: 16 trust_remote_code: true return_perf_metrics: true enable_iter_perf_stats: true enable_iter_req_stats: true perf_metrics_max_requests: 1000 EOF trtllm-serve serve /models/Qwen3-8B \ --host 0.0.0.0 \ --port 8000 \ --extra_llm_api_options /tmp/config.yaml ports: - containerPort: 8000 resources: limits: nvidia.com/gpu: 1 requests: nvidia.com/gpu: 1

注意model.aibrix.ai/engine: trtllm位于spec.template.metadata.labels(Pod 模板),而model.aibrix.ai/name同时出现在 Deployment 顶层 metadata 与 Pod 模板上——这与前文"标签应设置在 Pod 模板上"的约定一致。

TRT-LLM 的已知限制

  • 没有队列深度指标:TRT-LLM 不暴露num_requests_runningnum_requests_waiting。依赖队列深度的路由策略(例如least-request)将回退到随机路由(fall back to random routing)。
  • 指标依赖显式配置:只有当 TRT-LLM 服务端配置设置了return_perf_metrics: trueenable_iter_perf_stats: trueenable_iter_req_stats: true时,性能指标才会被导出。
  • 指标路径不同:TRT-LLM 的指标抓取路径是/prometheus/metrics而非/metrics,该逻辑由 pkg/metrics/engine_fetcher.go 的metricsPathForEngine统一处理,用户无需额外配置。

如何新增引擎(Adding New Engines)

若要支持一个新的引擎或新的指标类型,需要完成两步:

  1. 在指标名映射表中添加引擎类型:修改 pkg/metrics/metrics.go 中EngineMetricsNameMapping映射(例如为某个指标增加"newengine": "newengine:some_metric"条目),并补充引擎名常量(参考EngineNameVLLMEngineNameSGLangEngineNameTRTLLM的定义,pkg/metrics/metrics.go);
  2. 在 Deployment YAML 中允许新的引擎标签值:在model.aibrix.ai/engine标签上使用新引擎名。

更完整的实现细节可参考:

  • pkg/cache/cache_metrics.go — 指标抓取、调度、回退与标签清洗逻辑;
  • pkg/metrics/metrics.go — 指标注册表与引擎名映射。

从代码结构看,指标抓取层(EngineMetricsFetcher.FetchAllTypedMetrics)已经按"引擎类型 → 指标路径/映射"做了抽象(pkg/metrics/engine_fetcher.go),因此新增引擎时主要工作集中在映射表补充与标签值合法化,无需改动路由策略本身——这也是多引擎设计"即插即用"的关键所在。

小结

AIBrix 的多引擎支持通过"Pod 标签识别引擎 + 抽象指标名统一映射 + 路由策略自动降级"三层机制,让开发者在同一套集群内自由混排 vLLM、SGLang、xLLM 与 TRT-LLM 等引擎,既可用于引擎横向对比与基准测试,也可服务于模型分片与迁移等生产场景。接入新引擎时,只需补齐 pkg/metrics/metrics.go 中的指标映射并在 Deployment 上声明引擎标签,即可复用现有的缓存抓取与路由调度体系。

【免费下载链接】aibrixCost-efficient and pluggable Infrastructure components for GenAI inference项目地址: https://gitcode.com/GitHub_Trending/ai/aibrix

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 5:20:14

Scratch到Python的3D跑酷迁移:空间思维跃迁实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 5:18:36

Linux安装Docker避坑指南:从环境准备到常用配置

前阵子给一台刚装好的 Linux 服务器配置 Docker&#xff0c;过程没什么技术难度&#xff0c;但零零散散踩了几个小坑&#xff0c;比如系统源没换、镜像加速没配、权限不对导致反复 sudo。想了想干脆把完整的安装过程写成一篇图文解说版分享出来&#xff0c;标题看着是“Linux 下…

作者头像 李华
网站建设 2026/9/18 5:16:36

从codex迁移到workbuddy:本地AI工作台多模型接入实战

写下这篇的时候&#xff0c;我正好把主力AI编程助手从codex切到workbuddy满一周。这一周里&#xff0c;我顶着各种习惯上的不适应&#xff0c;把codex之前拖了我很久的几个痛点挨个验证了一遍&#xff0c;也把workbuddy的安装、模型接入、skill配置、自定义指令这些核心功能从头…

作者头像 李华
网站建设 2026/9/18 5:15:59

CANN opbase 算子开发指南:L0 基础张量操作接口 Reshape 详解

CANN opbase 算子开发指南&#xff1a;L0 基础张量操作接口 Reshape 详解 【免费下载链接】opbase 本项目是CANN算子库的基础框架库&#xff0c;为算子提供公共依赖文件和基础调度能力。 项目地址: https://gitcode.com/cann/opbase 导读 本文档详细讲解 CANN 算子库基…

作者头像 李华
网站建设 2026/9/18 5:15:42

从零搭建飞书GitHub更新简报机器人:LangBot+Dify+Astra实战

"GitBot 看看 LangBot 最近有没有什么值得关注的更新。"在飞书群里 机器人&#xff0c;随口问一句"最近 GitHub 上有什么更新"&#xff0c;几十秒后拿回一份由 GPT-6 Astra 生成的更新简报&#xff0c;这背后不是某个爬虫脚本&#xff0c;而是一套 LangBo…

作者头像 李华
网站建设 2026/9/18 5:15:07

Windows 11 屏幕保护程序配置与设置无效排查指南

屏幕保护程序在 Windows 11 里算不上什么新技术&#xff0c;但它绝对算得上"最容易出玄学问题"的系统设置之一。后台经常有人问我&#xff1a;明明在设置里挑了照片、气泡或者 Mystify&#xff0c;点完确定也生效了&#xff0c;回头再看一眼——"屏幕保护程序&q…

作者头像 李华