大模型多租户隔离:资源隔离、权限管控、性能互不干扰,SaaS落地场景实战.156

简介: 大模型多租户隔离是SaaS化核心,通过租户ID实现资源、权限与性能三重隔离:共享GPU/模型降低成本,逻辑隔离确保数据不交叉、请求不干扰、权限不越界,满足金融级安全与高并发稳定性要求。

一、大模型多租户隔离

1. 基础概念

       在SaaS软件即服务模式中,多租户指的是:一套大模型服务集群,同时为多个独立的租户(企业、用户、团队)提供服务,租户之间逻辑上完全独立、物理上共享基础设施;而多租户隔离,就是通过技术手段,让不同租户的请求、数据、资源、权限、性能完全互不干扰,实现共享一套服务,独享专属体验。

       放到大模型场景中,传统单租户大模型服务是一个企业买一套模型、一套服务器,自己用,成本极高、资源利用率极低;而大模型多租户隔离,是让金融、教育、电商等多个行业租户,共用同一套大模型、向量库、推理集群,但金融租户看不到教育租户的数据,电商租户不会占用金融租户的计算资源,一个租户请求拥堵不会影响其他租户。

156.2-ScreenShot_2026-04-21_184907_798.png

大模型多租户隔离的三大核心目标,也是SaaS场景的刚需:

  • 资源隔离:计算资源(GPU、CPU)、存储资源(模型缓存、向量数据)、网络资源,按租户分配,不越界占用;
  • 权限管控:租户只能访问自己的模型接口、私有数据、配置参数,杜绝越权访问;
  • 性能互不干扰:单个租户的高并发、大流量请求,不会导致其他租户响应延迟、推理失败,实现性能隔离。

       简单来说,大模型多租户隔离就是“一套房子住多户人家,每户有独立房间、独立水电、独立门锁,互不打扰”,是大模型SaaS化的核心基石。

2. 核心价值

       大模型的训练和推理高度依赖GPU、显存等稀缺资源,单租户部署成本动辄百万级,中小企业无法承担;而SaaS模式的核心是“规模化、低成本、易运维”,没有多租户隔离,大模型SaaS根本无法落地。

从业务和技术两个维度,其核心价值如下:

2.1 业务价值

  • 降本增效:共享基础设施,资源利用率从单租户的10%-20%提升至70%-90%,大幅降低单租户服务成本;
  • 快速规模化:无需为每个新租户单独部署模型、服务器,一键开通服务,SaaS平台可快速拓展海量租户;
  • 统一运维:一次升级、一次漏洞修复,全租户生效,运维成本降低90%以上。

2.2 技术价值

  • 数据安全合规:大模型处理的是租户核心数据,包括合同、客户信息、业务文档,隔离机制确保数据不泄露、不交叉,满足等保、GDPR等合规要求;
  • 服务稳定性保障:SaaS 平台服务海量租户,若没有性能隔离,一个租户的突发高并发(如电商大促、金融批量报表生成)会拖垮整个集群,导致全平台故障;
  • 精细化运营:支持按租户配置不同的模型版本、调用额度、推理参数,实现“基础版、企业版、旗舰版”的差异化SaaS服务。

3. 隔离维度

3.1 资源隔离:底层基础

资源隔离是多租户的物理、逻辑底层屏障,针对大模型的稀缺资源做精细化划分:

  • 计算资源:GPU显存、CPU核心、推理线程,按租户配额分配,禁止超额占用;
  • 存储资源:租户的私有向量库、对话历史、微调数据,独立存储,不与其他租户混存;
  • 中间件资源:消息队列、Redis缓存,按租户命名空间隔离,避免数据污染。

156.3-多租户资源配额对比.png

3.2 权限管控:安全防线

权限管控是多租户的访问安全锁,基于“身份认证 + 细粒度授权”实现:

  • 身份层:租户唯一标识TenantID,所有请求必须携带合法TenantID;
  • 权限层:接口权限(哪些模型接口可调用)、数据权限(哪些私有数据可访问)、操作权限(是否可微调模型、是否可导出数据);
  • 审计层:全量记录租户调用日志,追溯越权行为。

3.3 性能隔离:稳定性保障

性能隔离是多租户的服务质量护城河,解决租户间相互干扰问题:

  • 限流隔离:按租户设置每秒请求数QPS、并发数上限,超出直接拒绝,不占用公共资源;
  • 优先级隔离:企业版租户优先级高于基础版,高优请求优先分配资源;
  • 排队隔离:租户请求独立队列,避免一个租户的长耗时请求阻塞其他租户。

156.4-高并发场景:隔离机制对服务性能影响对比 llm_tenant_performance.png

这三大维度层层递进,构成了大模型多租户隔离的完整技术体系,缺一不可。

二、基础知识与原理

1. 多租户隔离的三种架构模式    

       多租户隔离有三种经典架构,从浅到深、隔离强度逐级提升,大模型SaaS场景需根据业务需求选择:

156.5-大模型多租户隔离架构图 llm_multi_tenant_architecture.png

1.1 共享数据库、共享Schema

  • 特点:最低隔离,低成本
  • 架构:所有租户共用同一数据库、同一数据表,通过TenantID字段区分数据;
  • 大模型适配:适合轻量级SaaS,如个人用户、小型团队,共享模型推理实例,仅通过TenantID区分对话历史;
  • 优缺点:成本最低、部署最简单,但隔离性最差,数据和性能易相互干扰。

1.2 共享数据库、独立Schema

  • 特点:中等隔离,平衡型
  • 架构:所有租户共用同一数据库,但每个租户拥有独立的数据表集合Schema;
  • 大模型适配:适合中小企业租户,共享模型集群,每个租户有独立的向量库、缓存空间;
  • 优缺点:隔离性中等,成本较低,满足大部分 SaaS 场景的安全和性能需求。

1.3 独立数据库、独立部署

  • 特点:最高隔离,高安全
  • 架构:每个租户拥有独立的数据库、独立的推理实例,物理层面完全隔离;
  • 大模型适配:适合金融、政府等对数据安全要求极高的租户,独享GPU资源;
  • 优缺点:隔离性拉满,性能完全独立,但成本最高、运维复杂。
  • 大模型SaaS主流选择:核心租户用独立数据库,普通租户用共享数据库 + 独立 Schema,平衡成本与隔离性。

156.6-大模型多租户三种架构:隔离强度与成本对比 llm_tenant_arch_compare.png

2. 大模型多租户隔离的基础原理

       大模型的核心流程分为请求接入→身份校验→资源分配→推理执行→结果返回,多租户隔离就是在这个流程的每一步植入”租户识别 + 隔离控制“逻辑,原理如下:

2.1 租户唯一标识原理

       每个租户在平台注册时,通过UUID或雪花算法生成全局唯一的TenantID,所有与租户相关的数据、资源、权限,都绑定TenantID。

  • 示例:租户A的TenantID=1001,其对话历史存储key为tenant:1001:chat:xxx,向量库集合为tenant_1001_collection。

2.2 请求拦截与校验原理

       所有大模型API请求,必须在请求头参数中携带TenantID和认证令牌Token,服务端通过拦截器统一校验:

  • 校验Token合法性,确认租户身份;
  • 校验TenantID是否存在,是否有权限访问请求的模型接口;
  • 校验租户调用额度是否耗尽,实现基础限流。

2.3 资源配额与隔离原理

基于令牌桶、漏桶算法实现资源配额管控,为每个租户分配固定的资源令牌:

  • 推理请求消耗令牌,令牌耗尽则拒绝请求;
  • GPU显存、缓存资源按TenantID划分空间,租户数据仅能写入自己的空间。

2.4 性能隔离原理

通过线程池隔离、队列隔离、优先级调度实现性能互不干扰:

  • 为每个租户创建独立的请求队列,高并发请求仅阻塞自身队列;
  • 按租户优先级分配GPU推理线程,高优租户优先执行。

3. 大模型多租户隔离与传统服务多租户的差异

       在没有深入理解前,我们通常都会把大模型多租户和传统Web服务多租户混淆,两者核心差异源于大模型的资源特性:

  • 1. 资源稀缺性不同:传统服务依赖CPU、内存,成本低;大模型依赖GPU、显存,稀缺且昂贵,必须极致共享 + 严格隔离;
  • 2. 请求耗时不同:传统接口请求毫秒级;大模型推理秒级,长耗时请求更容易阻塞集群,性能隔离要求更高;
  • 3. 数据特性不同:传统服务数据结构化;大模型包含非结构化文本、向量数据,数据隔离和存储复杂度更高;
  • 4. 状态性不同:传统服务无状态;大模型有对话上下文、微调状态,状态数据的隔离要求更严格。

这也是为什么大模型多租户隔离不能直接复用传统方案,需要针对性设计隔离机制。

三、多租户隔离的流程

1. 单租户大模型请求流程

先理解单租户流程,才能快速掌握多租户隔离逻辑:

156.7-单租户大模型请求流程 deepseek_mermaid_20260421_a45f9c.png

  • 1. 用户发起请求:调用大模型对话接口,传入问题;
  • 2. 服务接收请求:无身份校验,直接分配GPU资源;
  • 3. 模型推理:GPU执行推理,生成回答;
  • 4. 结果返回:返回给用户,流程结束。

缺陷:仅支持一个租户,资源闲置,无法SaaS化。

2. 多租户隔离完整执行流程

这是大模型SaaS平台的标准隔离流程,覆盖权限、资源、性能三大维度:

156.8-多租户隔离执行流程图.png

步骤 1:租户接入,携带唯一标识

租户调用大模型API,请求头必须携带:

  • TenantID:租户唯一标识;
  • Authorization:租户认证令牌;
  • 示例请求头:

headers = {

   "TenantID": "tenant_2024001",

   "Authorization": "Bearer xxxxxxx"

}

步骤 2:全局拦截器:权限管控(第一道隔离)

服务端启动租户拦截器,统一校验:

  • 1. 校验Token是否合法,拒绝无效请求;
  • 2. 校验TenantID是否在白名单,封禁未开通租户;
  • 3. 校验租户是否有权限访问当前模型接口,如禁止基础版租户访问指定参数量级别模型;
  • 4. 记录租户请求日志,用于审计。

步骤 3:限流校验:性能隔离(第二道隔离)

基于租户配额,执行限流控制:

  • 1. 读取租户配置:QPS上限=10,并发上限=5;
  • 2. 检查当前租户请求数是否超出配额,超出直接返回”请求超限“,不进入后续流程;
  • 3. 作用:避免单个租户高并发拖垮集群,实现性能互不干扰。

步骤 4:资源分配:资源隔离(第三道隔离)

按租户分配专属资源:

  • 1. 从租户资源池分配GPU显存或CPU 线程,禁止占用其他租户资源;
  • 2. 加载租户私有配置:模型温度、最大生成长度、私有向量库;
  • 3. 初始化租户独立缓存空间,存储对话上下文。

步骤 5:独立队列调度:性能深度隔离

租户请求进入独立队列,调度器按优先级处理:

  • 1. 企业版租户队列优先调度;
  • 2. 基础版租户队列排队执行,不影响高优租户;
  • 3. 长耗时推理请求仅阻塞自身队列,不干扰其他租户。

步骤 6:模型推理与数据隔离

推理过程中严格数据隔离:

  • 1. 仅读取租户私有数据,如私有文档、对话历史;
  • 2. 推理结果仅写入租户独立存储;
  • 3. 绝不跨租户读取、写入数据。

步骤 7:结果返回与资源释放

  • 1. 返回推理结果给租户;
  • 2. 释放租户占用的GPU、缓存资源,回归资源池;
  • 3. 更新租户调用额度,完成全流程。

四、应用实践

1. 大模型多租户隔离实现

       通过TenantID 拦截、限流、独立缓存、权限校验实现隔离核心,用简单的文本生成模拟大模型,突出核心业务,提高代码的可读性;

from fastapi import FastAPI, Header, HTTPException
from pydantic import BaseModel
import time
import uuid
from collections import defaultdict
# 初始化FastAPI应用
app = FastAPI(title="大模型多租户隔离实战Demo")
# ===================== 1. 多租户核心配置:权限、资源、限流 =====================
# 租户配置库:存储TenantID、权限、限流配额、资源配额
# 格式:{租户ID: {"name": "租户名称", "model_perm": ["模型接口列表"], "qps": 每秒请求数, "quota": 剩余调用额度}}
TENANT_CONFIG = {
    "tenant_001": {
        "name": "电商企业租户",
        "model_perm": ["llm_chat", "llm_summary"],
        "qps": 5,
        "quota": 1000,
        "gpu_quota": 2  # 分配2GB显存资源
    },
    "tenant_002": {
        "name": "教育小型租户",
        "model_perm": ["llm_chat"],
        "qps": 2,
        "quota": 500,
        "gpu_quota": 1  # 分配1GB显存资源
    }
}
# 租户独立缓存:模拟Redis命名空间隔离,存储对话历史
TENANT_CACHE = defaultdict(dict)
# 租户请求计数器:用于限流(性能隔离)
TENANT_REQUEST_COUNTER = defaultdict(int)
# ===================== 2. 模拟大模型推理函数 =====================
def mock_llm_infer(tenant_id: str, prompt: str) -> str:
    """模拟大模型推理,仅使用租户自身缓存/资源"""
    # 数据隔离:仅读取当前租户的对话历史
    chat_history = TENANT_CACHE[tenant_id].get("chat_history", [])
    chat_history.append(prompt)
    TENANT_CACHE[tenant_id]["chat_history"] = chat_history[-5:]  # 保留最近5轮对话
    
    # 模拟推理耗时
    time.sleep(0.5)
    return f"【租户{tenant_id}】模型回答:已处理你的问题「{prompt}」,对话历史:{len(chat_history)}轮"
# ===================== 3. 多租户隔离核心中间件 =====================
def check_tenant_isolation(tenant_id: str, token: str, model_name: str):
    """
    多租户三合一校验:
    1. 权限管控(身份+接口权限)
    2. 性能隔离(限流)
    3. 资源隔离(调用额度)
    """
    # -------------- 权限管控:身份校验 --------------
    if tenant_id not in TENANT_CONFIG:
        raise HTTPException(status_code=403, detail=f"租户[{tenant_id}]不存在,无访问权限")
    
    tenant_name = TENANT_CONFIG[tenant_id]["name"]
    
    # 权限管控:接口访问权限校验
    if model_name not in TENANT_CONFIG[tenant_id]["model_perm"]:
        raise HTTPException(status_code=403, detail=f"租户[{tenant_name}]无权限访问{model_name}接口")
    
    # -------------- 性能隔离:限流管控 --------------
    if TENANT_REQUEST_COUNTER[tenant_id] >= TENANT_CONFIG[tenant_id]["qps"]:
        raise HTTPException(status_code=429, detail=f"租户[{tenant_name}]请求超限,性能隔离触发")
    TENANT_REQUEST_COUNTER[tenant_id] += 1
    
    # -------------- 资源隔离:调用额度管控 --------------
    if TENANT_CONFIG[tenant_id]["quota"] <= 0:
        raise HTTPException(status_code=402, detail=f"租户[{tenant_name}]资源额度耗尽,资源隔离触发")
    TENANT_CONFIG[tenant_id]["quota"] -= 1
# ===================== 4. 多租户大模型API =====================
class LLMRequest(BaseModel):
    prompt: str
    model_name: str = "llm_chat"
@app.post("/llm/chat")
def llm_chat(request: LLMRequest, TenantID: str = Header(...), Authorization: str = Header(...)):
    """
    多租户隔离大模型对话接口
    必须携带请求头:TenantID、Authorization
    """
    # 执行三合一隔离校验
    check_tenant_isolation(TenantID, Authorization, request.model_name)
    
    # 执行模型推理(数据隔离)
    response = mock_llm_infer(TenantID, request.prompt)
    
    # 释放计数器
    TENANT_REQUEST_COUNTER[TenantID] -= 1
    
    return {
        "code": 200,
        "tenant_id": TenantID,
        "response": response,
        "remaining_quota": TENANT_CONFIG[TenantID]["quota"]
    }
# ===================== 5. 直接启动(无需命令行)=====================
if __name__ == "__main__":
    import uvicorn
    print("🚀 启动多租户大模型服务...")
    print("📍 服务地址: http://0.0.0.0:8010")
    print("📖 API文档: http://0.0.0.0:8010/docs")
    uvicorn.run(app, host="0.0.0.0", port=8010)

image.gif

1.1 代码说明

1.1.1 权限管控实现

  • 通过TENANT_CONFIG存储租户权限,仅允许访问配置内的模型接口;
  • 校验TenantID合法性,拒绝未授权租户,实现身份隔离。

1.1.2 性能隔离实现

  • 基于TENANT_REQUEST_COUNTER实现租户级限流,超出QPS直接拒绝;
  • 每个租户请求独立计数,互不干扰,解决性能拥堵问题。

1.1.3 资源隔离实现

  • 租户拥有独立的调用额度,耗尽后无法使用服务;
  • TENANT_CACHE按TenantID划分独立空间,对话历史完全隔离,不交叉污染。

1.1.4 测试方法

  • 1. 运行代码,打开http://127.0.0.1:8010/docs
  • 2. 携带TenantID: tenant_001调用接口,正常返回;
  • 3. 使用tenant_001调用llm_summary,有权限;使用tenant_002调用,无权限;
  • 4. 快速多次调用,触发限流,验证性能隔离。

1.2 启动服务

156.9-启动服务 ScreenShot_2026-04-21_153857_812.png

1.3 接口入参说明

156.10-接口参考文档 ScreenShot_2026-04-21_161957_091.png

1.3.1 请求头 (Headers)

  • TenantID,必填,租户ID,如 tenant_001、tenant_002
  • Authorization,授权令牌,以Bearer xxx开头的任意字符

1.3.2 请求体 (Body)

  • prompt,必填,表示用户输入的问题
  • model_name,模型接口名,默认值为llm_chat,可选llm_chat、llm_summary

{

 "prompt": "你的问题内容",

 "model_name": "llm_chat"

}

1.4 curl语法简单测试

1.4.1 tenant_001正常调用ll_chat返回

curl -X POST "http://localhost:8010/llm/chat" -H "TenantID: tenant_001" -H "Authorization: Bearer xxx" -H "Content-Type: application/json" -d "{\"prompt\": \"你好,请介绍一下自己\", \"model_name\": \"llm_chat\"}"

image.gif

1.4.2 传入不存在的tenant_005租户

curl -X POST "http://localhost:8010/llm/chat" -H "TenantID: tenant_005" -H "Authorization: Bearer xxx" -H "Content-Type: application/json" -d "{\"prompt\": \"你好,请介绍一下自己\", \"model_name\": \"llm_chat\"}"

image.gif

1.4.3 tenant_002没有llm_summary权限

curl -X POST "http://localhost:8010/llm/chat" -H "TenantID: tenant_002" -H "Authorization: Bearer xxx" -H "Content-Type: application/json" -d "{\"prompt\": \"你好,请介绍一下自己\", \"model_name\": \"llm_summary\"}"

image.gif

156.11-简单curl测试 ScreenShot_2026-04-21_160546_931.png

1.5 简单测试脚本

import requests
response = requests.post(
    "http://localhost:8010/llm/chat",
    headers={
        "TenantID": "tenant_001",
        "Authorization": "Bearer xxx",
        "Content-Type": "application/json"
    },
    json={
        "prompt": "你好,请介绍一下自己",
        "model_name": "llm_chat"
    }
)
print(response.json())

image.gif

测试输出:

{'code': 200, 'tenant_id': 'tenant_001', 'response': '【租户tenant_001】模型回答:已处理你的问题「你好,请介绍一下自己」,对话历史:6轮', 'remaining_quota': 986}

2. 完整的测试细节

       测试覆盖的隔离维度包括: 权限隔离(身份校验、接口权限)、性能隔离(滑动窗口限流 QPS)、资源隔离(调用额度配额)、数据隔离(租户独立缓存)

测试脚本包含以下8个测试场景:

序号 测试函数 测试场景 说明
1 test_normal_request() 正常请求测试 验证基本功能是否正常,使用 tenant_001 发送标准对话请求
2 test_tenant_isolation() 多租户数据隔离测试 验证 tenant_001 和 tenant_002 的数据相互隔离
3 test_rate_limit() 限流测试(并发) 5 个线程并发请求,tenant_002 QPS=2,验证超限时返回 429
4 test_concurrent_rate_limit() 并发限流测试 10 个线程同时请求,tenant_001 QPS=5,统计成功/限流数量
5 test_invalid_tenant() 非法租户测试 使用不存在的 tenant_999,验证返回 403
6 test_no_permission() 无接口权限测试 tenant_002 调用未授权的 llm_summary 接口,验证返回 403
7 test_quota_exhausted() 额度耗尽测试 连续发送请求消耗额度,演示额度扣减机制
8 test_stress() 压力测试 10 秒内持续发送请求,统计成功率和平均 QPS
"""
多租户大模型服务 - 测试脚本合集
包含:正常请求、限流测试、权限测试、额度耗尽测试
"""
import requests
import threading
import time
import json
BASE_URL = "http://localhost:8010"
# ===================== 测试配置 =====================
TENANT_001 = {"id": "tenant_001", "name": "电商企业租户", "auth": "Bearer token001"}
TENANT_002 = {"id": "tenant_002", "name": "教育小型租户", "auth": "Bearer token002"}
INVALID_TENANT = {"id": "tenant_999", "name": "非法租户", "auth": "Bearer xxx"}
def print_result(test_name, response):
    """打印测试结果"""
    print(f"\n{'='*60}")
    print(f"【{test_name}】")
    print(f"{'='*60}")
    print(f"状态码: {response.status_code}")
    try:
        print(f"响应内容: {json.dumps(response.json(), ensure_ascii=False, indent=2)}")
    except:
        print(f"响应内容: {response.text}")
# ===================== 1. 正常请求测试 =====================
def test_normal_request():
    """正常对话请求测试"""
    url = f"{BASE_URL}/llm/chat"
    headers = {
        "TenantID": TENANT_001["id"],
        "Authorization": TENANT_001["auth"],
        "Content-Type": "application/json"
    }
    data = {
        "prompt": "你好,请介绍一下自己",
        "model_name": "llm_chat"
    }
    response = requests.post(url, headers=headers, json=data)
    print_result("正常请求测试", response)
    return response
# ===================== 2. 限流测试(高频请求)=====================
def test_rate_limit():
    """限流测试 - 并发发送多个请求触发限流"""
    url = f"{BASE_URL}/llm/chat"
    headers = {
        "TenantID": TENANT_002["id"],  # 教育租户 QPS=2
        "Authorization": TENANT_002["auth"],
        "Content-Type": "application/json"
    }
    data = {"prompt": "测试限流", "model_name": "llm_chat"}
    
    print(f"\n{'='*60}")
    print("【限流测试】并发发送5个请求(租户QPS限制为2)")
    print(f"{'='*60}")
    
    results = [None] * 5
    
    def send_request(idx):
        response = requests.post(url, headers=headers, json=data)
        results[idx] = (idx, response)
    
    # 创建线程
    threads = []
    for i in range(5):
        t = threading.Thread(target=send_request, args=(i,))
        threads.append(t)
    
    # 几乎同时启动所有线程
    for t in threads:
        t.start()
    
    for t in threads:
        t.join()
    
    # 打印结果
    for idx, response in sorted(results, key=lambda x: x[0]):
        status = "✓ 成功" if response.status_code == 200 else f"✗ 被限流"
        detail = ""
        if response.status_code == 429:
            detail = f" - {response.json().get('detail', '')[:40]}"
        print(f"  请求{idx+1}: {status} (HTTP {response.status_code}){detail}")
    
    return [r[1] for r in results]
# ===================== 3. 并发限流测试 =====================
def test_concurrent_rate_limit():
    """并发请求测试"""
    url = f"{BASE_URL}/llm/chat"
    headers = {
        "TenantID": TENANT_001["id"],  # 电商租户 QPS=5
        "Authorization": TENANT_001["auth"],
        "Content-Type": "application/json"
    }
    data = {"prompt": "并发测试", "model_name": "llm_chat"}
    
    print(f"\n{'='*60}")
    print("【并发限流测试】同时启动10个线程请求(租户QPS限制为5)")
    print(f"{'='*60}")
    
    results = {"success": 0, "rate_limited": 0}
    
    def make_request():
        try:
            response = requests.post(url, headers=headers, json=data, timeout=5)
            if response.status_code == 200:
                results["success"] += 1
            elif response.status_code == 429:
                results["rate_limited"] += 1
        except Exception as e:
            print(f"  请求异常: {e}")
    
    threads = []
    for i in range(10):
        t = threading.Thread(target=make_request)
        threads.append(t)
    
    # 同时启动所有线程
    for t in threads:
        t.start()
    
    for t in threads:
        t.join()
    
    print(f"  成功: {results['success']} 个")
    print(f"  被限流: {results['rate_limited']} 个")
# ===================== 4. 权限测试(非法租户)=====================
def test_invalid_tenant():
    """非法租户测试"""
    url = f"{BASE_URL}/llm/chat"
    headers = {
        "TenantID": INVALID_TENANT["id"],
        "Authorization": INVALID_TENANT["auth"],
        "Content-Type": "application/json"
    }
    data = {"prompt": "测试", "model_name": "llm_chat"}
    response = requests.post(url, headers=headers, json=data)
    print_result("非法租户测试", response)
    return response
# ===================== 5. 权限测试(无接口权限)=====================
def test_no_permission():
    """无接口权限测试 - tenant_002 没有 llm_summary 权限"""
    url = f"{BASE_URL}/llm/chat"
    headers = {
        "TenantID": TENANT_002["id"],
        "Authorization": TENANT_002["auth"],
        "Content-Type": "application/json"
    }
    data = {"prompt": "总结这段文本", "model_name": "llm_summary"}
    response = requests.post(url, headers=headers, json=data)
    print_result("无接口权限测试", response)
    return response
# ===================== 6. 额度耗尽测试 =====================
def test_quota_exhausted():
    """额度耗尽测试 - 快速消耗完租户额度"""
    url = f"{BASE_URL}/llm/chat"
    headers = {
        "TenantID": TENANT_002["id"],  # 教育租户 quota=500
        "Authorization": TENANT_002["auth"],
        "Content-Type": "application/json"
    }
    data = {"prompt": "消耗额度", "model_name": "llm_chat"}
    
    print(f"\n{'='*60}")
    print("【额度耗尽测试】快速发送请求消耗额度")
    print(f"{'='*60}")
    
    # 先发送几个正常请求
    for i in range(3):
        response = requests.post(url, headers=headers, json=data)
        if response.status_code == 200:
            remaining = response.json().get("remaining_quota", "未知")
            print(f"  请求{i+1}: 成功,剩余额度: {remaining}")
    
    # 模拟额度耗尽(直接修改配置,实际测试用)
    print("  ...模拟额度耗尽...")
    # 这里只是演示,实际需要通过大量请求或修改服务端配置
# ===================== 7. 多租户隔离测试 =====================
def test_tenant_isolation():
    """多租户数据隔离测试"""
    url = f"{BASE_URL}/llm/chat"
    
    print(f"\n{'='*60}")
    print("【多租户隔离测试】两个租户分别发送请求")
    print(f"{'='*60}")
    
    for tenant in [TENANT_001, TENANT_002]:
        headers = {
            "TenantID": tenant["id"],
            "Authorization": tenant["auth"],
            "Content-Type": "application/json"
        }
        data = {"prompt": "这是第一条消息", "model_name": "llm_chat"}
        response = requests.post(url, headers=headers, json=data)
        
        if response.status_code == 200:
            resp_data = response.json()
            print(f"  {tenant['name']}: {resp_data.get('response', '')}")
        else:
            print(f"  {tenant['name']}: 请求失败 {response.status_code}")
# ===================== 8. 压力测试 =====================
def test_stress():
    """压力测试 - 持续发送请求"""
    url = f"{BASE_URL}/llm/chat"
    headers = {
        "TenantID": TENANT_001["id"],
        "Authorization": TENANT_001["auth"],
        "Content-Type": "application/json"
    }
    data = {"prompt": "压力测试", "model_name": "llm_chat"}
    
    print(f"\n{'='*60}")
    print("【压力测试】10秒内持续发送请求")
    print(f"{'='*60}")
    
    success = 0
    failed = 0
    start_time = time.time()
    
    while time.time() - start_time < 10:
        response = requests.post(url, headers=headers, json=data)
        if response.status_code == 200:
            success += 1
        else:
            failed += 1
        time.sleep(0.2)  # 200ms间隔
    
    print(f"  10秒内成功: {success} 个")
    print(f"  被限流/失败: {failed} 个")
    print(f"  平均每秒: {(success+failed)/10:.1f} 请求")
# ===================== 主程序 =====================
if __name__ == "__main__":
    print("🚀 多租户大模型服务测试脚本")
    print(f"服务端地址: {BASE_URL}")
    print("="*60)
    
    # 检查服务是否可用
    try:
        requests.get(f"{BASE_URL}/docs", timeout=3)
        print("✅ 服务连接正常\n")
    except:
        print("❌ 无法连接到服务,请确保服务端已启动")
        print(f"   启动命令: python 260421.(156)1-main.py")
        exit(1)
    
    # 执行测试
    test_normal_request()
    test_tenant_isolation()
    test_rate_limit()
    test_concurrent_rate_limit()
    test_invalid_tenant()
    test_no_permission()
    test_quota_exhausted()
    test_stress()
    
    print(f"\n{'='*60}")
    print("✅ 所有测试执行完成")
    print(f"{'='*60}")

image.gif

输出结果:

🚀 多租户大模型服务测试脚本

服务端地址: http://localhost:8010

============================================================

✅ 服务连接正常

============================================================

【正常请求测试】

============================================================

状态码: 200

响应内容: {

 "code": 200,

 "tenant_id": "tenant_001",

 "response": "【租户tenant_001】模型回答:已处理你的问题「你好,请介绍一下自己」,对话历史:1轮",

 "remaining_quota": 999

}

============================================================

【多租户隔离测试】两个租户分别发送请求

============================================================

 电商企业租户: 【租户tenant_001】模型回答:已处理你的问题「这是第一条消息」,对话历史:2轮

 教育小型租户: 【租户tenant_002】模型回答:已处理你的问题「这是第一条消息」,对话历史:1轮

============================================================

【限流测试】并发发送5个请求(租户QPS限制为2)

============================================================

 请求1: ✓ 成功 (HTTP 200)

 请求2: ✓ 成功 (HTTP 200)

 请求3: ✗ 被限流 (HTTP 429) - 租户[教育小型租户]请求超限(QPS:2),性能隔离触发

 请求4: ✗ 被限流 (HTTP 429) - 租户[教育小型租户]请求超限(QPS:2),性能隔离触发

 请求5: ✗ 被限流 (HTTP 429) - 租户[教育小型租户]请求超限(QPS:2),性能隔离触发

============================================================

【并发限流测试】同时启动10个线程请求(租户QPS限制为5)

============================================================

 成功: 5 个

 被限流: 5 个

============================================================

【非法租户测试】

============================================================

状态码: 403

响应内容: {

 "detail": "租户[tenant_999]不存在,无访问权限"

}

============================================================

【无接口权限测试】

============================================================

状态码: 403

响应内容: {

 "detail": "租户[教育小型租户]无权限访问llm_summary接口"

}

============================================================

【额度耗尽测试】快速发送请求消耗额度

============================================================

 请求1: 成功,剩余额度: 496

 请求2: 成功,剩余额度: 495

 请求3: 成功,剩余额度: 494

 ...模拟额度耗尽...

============================================================

【压力测试】10秒内持续发送请求

============================================================

 10秒内成功: 4 个

 被限流/失败: 0 个

 平均每秒: 0.4 请求

============================================================

✅ 所有测试执行完成

============================================================

五、总结

       简单来说,大模型多租户隔离的核心逻辑,就是共用一套底层GPU、模型、存储资源,通过租户唯一标识做逻辑切割,既解决了大模型部署成本高、资源浪费的问题,又能守住数据安全、访问权限与服务稳定的底线。区别于传统业务多租户,大模型推理耗时久、硬件资源稀缺,因此限流队列、显存配额、独立数据空间这类隔离设计,都是保障平台平稳运行的关键。

       多租户隔离不只是单纯的技术配置,更是大模型从单点部署走向商业化SaaS服务的必经门槛。很多时候大模型功能落地不难,难的是多用户并发下的平衡与风控。所以我们首先要理解租户拦截、限流、数据隔离的运行逻辑;后续可以逐步延伸到显存隔离、向量库租户拆分、灰度资源调度等进阶内容,循序渐进积累应用落地能力,才能逐步吃透大模型线上服务的核心技术。

相关文章
|
5天前
|
人工智能 JSON 自然语言处理
让教学更智慧:用阿里云百炼工作流,自动生成中小学教材内容#小有可为#有温度的AI
通过可视化工作流编排,将大模型推理能力转化为标准化的教学内容生成引擎。教师只需输入教材标题和适用学段,即可自动获得结构完整、符合课程标准的章节内容,大幅降低备课门槛,助力教育资源均衡化。
456 123
|
7天前
|
人工智能 定位技术 SEO
我学 GEO 第 15 天:终于知道AI GEO该如何做?
我是暴走的莉莉酱,边旅行边研究AI GEO的数字游民。专注普通人如何提升“AI可见度”——让AI在回答用户问题时准确识别、理解并推荐你。不讲玄学,只做可测、可调、可持续的GEO实践。
438 126
|
9天前
|
机器学习/深度学习 人工智能 调度
🐴 HappyHorse 1.1 现已上线阿里云百炼!快来查收模型使用指南,现在调用享 6 折~
HappyHorse 1.1 是新一代视频生成大模型,全面升级动态表现力、角色一致性、指令遵循、视觉质感与音画协同能力。支持I2V/T2V/R2V三类生成,适配短剧、电商广告、品牌营销等场景,提供高质、流畅、可控的AI视频生产力。
737 5
🐴 HappyHorse 1.1 现已上线阿里云百炼!快来查收模型使用指南,现在调用享 6 折~
|
7天前
|
缓存 人工智能 运维
阿里云618百炼大模型Qwen3.7-Max功能、免费试用、订阅计费、配置接入详解
Qwen3.7-MAX是阿里云百炼平台推出的通义千问3.7系列旗舰大语言模型,专为智能体时代复杂任务打造,依托阿里云全域算力与自研技术,在逻辑推理、长文本处理、代码工程、长周期自主执行等领域达到行业顶尖水平。2026年618期间,该模型推出多重免费试用权益、按量计费5折、订阅套餐优惠等专属福利,覆盖个人开发者、团队与企业全场景需求,以下从核心功能、免费试用、订阅计费、配置接入四方面展开详细解析。
437 123
|
5天前
|
人工智能 自然语言处理 API
阿里云Token Plan团队版解析:功能、三档套餐与省钱订阅指南
阿里云百炼平台推出的Token Plan团队版,是面向企业与团队的AI大模型订阅服务,以Credits为统一计量单位,整合文本与图像生成模型,提供团队管理、数据安全、多工具兼容等核心能力,解决团队零散订阅AI服务的管理混乱、成本失控、数据安全等痛点。本文将从核心定位、套餐详情、计费规则、团队管理、工具兼容、便宜订阅技巧等方面,全面解析Token Plan团队版,帮助企业与团队高效、低成本地使用AI服务。
323 108
|
14天前
|
Linux 程序员 数据格式
【2026最新】Notepad++下载、安装和使用一篇搞定(附中文版安装包)
Notepad++ 是一款免费开源、轻量高效的 Windows 文本编辑器,支持 C/Python/HTML 等 80+ 语言语法高亮、代码折叠、正则替换、编码转换及插件扩展,专为程序员与文本处理用户打造,完美替代系统记事本。(239字)
|
6天前
|
存储 人工智能 数据可视化
别再手动复制 Skill 了:多 Agent 时代的 Skill 管理方案
多 Agent 场景下 Skill 的统一管理与同步。
300 123
|
9天前
|
存储 人工智能 监控
QoderWork完全指南:从入门到精通,把“AI实习生”变成你的全能工作搭档
阿里云2026年推出的桌面端AI工作助手QoderWork,不止聊天,更可动手干活:本地运行、安全可控,支持文件整理、数据分析、PPT生成、网页开发等;内置专家套件、多Agent协作与自定义Skills,让AI真正成为你身边的“AI实习生”。

热门文章

最新文章