跳到主要内容

多租户 AI 系统:大规模场景下的隔离、定制与成本归因

· 阅读需 12 分钟
Tian Pan
Software Engineer

大多数在大语言模型(LLM)之上构建 SaaS 产品的团队都是通过惨痛的教训才发现多租户问题的:他们利用单一的共享提示词配置快速出海,然后惊恐地发现一个客户的系统提示词泄露到了另一个客户的响应中,或者某个企业级客户耗尽了所有人的速率限制,亦或是当月 AI 账单寄来时,根本无法确定是哪个客户造成了 40% 的支出。这种失败模式并非停留在理论层面——NDSS 2025 的一篇论文证明,vLLM、SGLang、LightLLM 和 DeepSpeed 中的前缀缓存(prefix caching)可以被利用,仅通过时间信号和精心构造的请求,就能以 99% 的准确率重建另一个租户的提示词。

构建多租户 AI 基础设施与传统数据库的多租户化并不相同。共享组件——推理服务器、KV 缓存、嵌入流水线、检索索引——每一个都面临独特的隔离挑战。这篇文章涵盖了你实际必须解决的四个问题:隔离、定制、成本归因以及单租户质量追踪。

隔离问题比你想象的更严重

在传统的 Web 应用中,租户隔离主要是一个数据库 schema 决策。而在 AI 系统中,隔离必须在请求管道的每一层强制执行:身份验证、租户解析、上下文编译、推理和缓存。

正确的顺序至关重要。身份验证必须发生在租户解析之前;租户解析发生在会话派生之前;会话加载发生在上下文编译之前。跳过或重新排列任何步骤,你都有混淆上下文的风险。这听起来显而易见,直到你在调试一个代理框架(agent framework)时,发现中间件的运行顺序与你预期的不同,导致某个企业客户偶尔会收到另一个客户的会话历史记录。

最棘手的隔离失败模式在于前缀缓存。现代推理服务器会缓存常用提示词前缀的键值(KV)注意力状态,以避免在每个请求中重复计算。当两个租户恰好共享一个提示词前缀时——例如通用的系统提示词模板——它们的 KV 缓存块可能会共存于同一个 GPU 内存池中。如果没有适当的隔离,攻击者可以通过发出探测缓存命中的定时请求来重建受害者租户的提示词。

2025 年添加到 vLLM 中的修复方案是 cache_salt:这是一个针对每个请求的参数,它会对块哈希进行加盐处理,使得两个文本相同的请求产生不同的缓存键。这会让你付出跨租户缓存重用的成本,但这种权衡几乎总是正确的。另一种选择是默认接受数据泄露风险。

RAG 系统的数据隔离较为简单,但仍需要深思熟虑的设计。标准模式是每个租户拥有一个向量数据库命名空间(或独立的 collection),并在查询时强制执行租户 ID 校验,而不只是在插入时。如果你的检索层在接受租户 ID 作为用户提供的参数时,没有针对已验证的会话进行重新验证,那么你就存在水平越权漏洞。

无需为每个客户重构的定制化

共享基础设施的吸引力在于成本,而单租户定制化的吸引力在于产品差异化。这两个目标背道而驰,但行业已经收敛于几种让你两者兼得的模式。

系统提示词和护栏(guardrail)配置是摩擦力最低的定制形式。每个租户获得一个配置记录,指定其系统提示词模板、启用的护栏以及任何覆盖设置。在请求时,网关将租户配置与传入的请求合并。像 LiteLLM 和 NVIDIA NeMo Guardrails 这样的框架都原生支持这种模式。配置存储成本很低;基础模型是共享的。

模型路由是更高一级的方案。一些租户为 GPT-4 级别的模型付费;另一些则使用更小、更便宜的模型。一些租户需要低延迟流式传输;另一些则可以容忍批处理。单租户路由表将租户等级映射到模型选择。这在操作上很直接,但引入了定价复杂性:你的成本归因不仅需要追踪 token 数量,还需要追踪每个租户在每个模型上消耗的 token 数量。

通过 LoRA 适配器(adapters)进行单租户微调是更有趣的地方。你无需为每个客户训练一个独立的模型,而是在客户特定的数据上训练一个微型适配器(通常为几十 MB),并在推理时将其加载到共享的基础模型之上。像 LoRAX 这样的框架可以通过动态适配器加载和高效批处理适配器计算的 Punica CUDA 内核,在单块 GPU 上支持数千个 LoRA 适配器。AWS SageMaker 通过“每个请求一个适配器”的路由方式支持相同的模式。结果是:以接近共享模型的硬件成本,实现单租户的模型行为。

限流(Rate limiting)值得专门提及,因为团队经常在执行点上出错。在 LLM 调用之后检查 token 预算是徒劳的——token 已经消耗了。预算强制执行必须发生在调度推理之前的入口点,通过硬性限制在租户达到上限时拒绝或排队请求。仅在代理的最外层进行检查也是不够的;如果代理在每个用户轮次中进行多次 LLM 调用,你需要在执行路径的更深处进行单次调用计费。

成本归因:无人预料到的计费难题

统计 Token 很容易。规模化的多租户成本归因则不然。两者之间的差距是大多数团队浪费数月工程时间的地方。

最小可行方案:在每个推理请求离开网关之前,为其打上 tenant_idfeature_idmodel_version 的标签。然后将使用情况元数据(输入 Token、输出 Token、模型)流式传输到成本追踪存储中。一旦有了元数据,聚合查询(按租户划分的月度支出、每个功能的成本、不同客户层级的模型分布)就会变得非常简单。如果你忘记打标签,事后将无法追溯重构。

缓存会从两个方面增加归因的复杂性。首先,共享前缀缓存意味着某些租户会从他人付费预热的缓存命中中受益。是奖励预热缓存的租户,还是分摊所有受益者的成本,这更多是一个会计决策,而非技术决策——但在你的计费系统上线之前,你需要做出决定。其次,租户特定的缓存(例如 LMCache 这种在外部 KV 缓存中为每个租户划分独立命名空间的方法)消除了歧义,但会消耗更多内存。

模型路由会让复杂度倍增:来自租户 A 的单个请求可能会分发到嵌入模型、重排序模型(reranker)和生成模型,而每个模型的 Token 单价都不同。成本归因需要追踪链路中的每一个跳跃(hop),而不仅仅是最后的生成调用。像 Cloudflare AI Gateway 和 OpenRouter 这样的 AI 网关提供了跨供应商的请求级遥测,这在你的模型栈跨越多个厂商时非常有用。

预算控制是运维的安全网。实践模式:设置 80% 预算的软限制(soft limit),并向客户团队发送警报;设置 100% 的硬限制(hard limit),要么将非紧急请求排队,要么直接拒绝并返回明确的错误。跳过硬限制的团队会在月底结算时发现,某个行为异常的代理(agent)运行了一整晚,导致客户账单翻了三倍。

租户级质量追踪

这是最不成熟的领域,也是在生产环境出问题前最容易被忽视的领域。

在单租户系统中,你的评估套件覆盖了整个产品。但在多租户系统中,提升平均质量的模型更新或提示词(prompt)更改仍可能降低特定租户的质量——尤其是那些使用非标准语言、领域特定术语或高度调优的系统提示词的租户。聚合指标会掩盖单个租户的质量退化。

最小投入:在任何提示词或模型更改发布前,在测试环境(staging)中对每个租户的评估集进行影子测试(shadow-run)。评估集不需要很大——覆盖其实际使用模式的几百个示例就足以捕捉退化。基础设施成本较低;虽然维护租户评估集的运维开销是实打实的,但一旦你有了企业客户,这就是必须的。

延迟追踪也应该是针对每个租户的,而不只是针对每个端点。不同的租户配置具有不同的延迟画像:一个具有长系统提示词、结合了 RAG 检索并包含防护栏(guardrails)的租户,其延迟底线与直接进行补全调用的租户有本质区别。如果只对所有租户的平均延迟报警,直到客户提交支持工单前,你都会漏掉特定租户的性能退化。

另一个值得监测的信号是行为数据:每个租户的重试率、会话放弃率和编辑率。这些是质量问题的先行指标,会在显式反馈出现前浮现。如果租户 A 的重试率在模型更改后上升了 15%,说明其特定配置在新模型上的表现不佳,即使其他信号尚未触发。

推理中的“喧闹邻居”问题

不同于 Web 服务器中计算密集型租户只会减慢请求处理速度,在 AI 基础设施中,失控的租户会损耗 GPU 显存、耗尽 KV 缓存容量,并导致所有人的调度队列堆积。LLM 推理负载的波动性特别大:一个运行文档处理批处理作业的租户可能会消耗所有可用的解码能力,迫使其他租户的请求进入长达数秒的队列等待。

防御策略(按实施成本排序):

网关层的速率限制是最基础的。针对每个租户的请求速率限制和并发请求限制,可以防止单个客户垄断调度队列。应按租户层级设置限制,而非仅进行全局设置。

租户资源配额需要基础设施层面的支持:容器资源限制、连接池配额,如果你正在使用 vLLM 的解耦服务(disaggregated serving,将预填充 prefill 和解码 decode 分散在不同服务器上),还需要租户级的调度优先级。解耦服务很有帮助,因为预填充密集型请求(如长提示词、文档处理)会与解码密集型请求隔离,不会剥夺交互式租户的“首字生成时间”(TTFT)。

为高级租户提供专用算力是终极方案。Azure OpenAI 的预置吞吐量单位(PTU)、Together AI 的推理端点以及 AWS Bedrock 的预置模型都遵循同一种模式:租户为预留容量付费,该容量在物理上与共享池隔离。这消除了“喧闹邻居”问题,但也消除了共享基础设施带来的成本节省。对于企业级 SLA 来说,这是正确的选择,但不适用于长尾客户。

总结

在这些约束条件下形成的架构如下所示:一个在任何请求到达推理层之前,强制执行身份验证、租户解析、限流和预算检查的网关;一个驱动模型路由、系统提示词注入和护栏选择的针对每个租户的配置存储;一个共享的基础模型,带有可选的、在服务时动态加载的租户专属 LoRA 适配器;具有缓存加盐的前缀缓存,以在不发生跨租户缓存冲突的情况下保持吞吐量;以及一个遥测流水线,为每个操作标记租户元数据,用于成本归因和质量跟踪。

这些基础设施并非什么新鲜事物。这些组件存在于开源项目(vLLM、LiteLLM、LoRAX、LMCache)和托管服务(Azure PTUs、AWS SageMaker 多适配器服务)中。工程工作在于集成和运营,而非发明。

真正困难的是组织纪律:确保每一个涉及推理的新功能都通过同一个租户感知网关,确保成本归因标签在时间紧迫的部署中从未被遗漏,并确保在客户的使用模式发生变化时,针对每个租户的评估集能得到更新。多租户 AI 系统之所以失败,并不是因为缺少基础设施原语,而是因为团队是在应对事故时零敲碎打地添加它们,而不是从一开始就将它们构建到基础架构中。

References:Let's stay in touch and Follow me for more thoughts and updates