简介
多租户(Multi-tenancy)指一套服务实例,同时为多个独立客户(租户)提供 Claude Agent 能力,租户之间数据、会话、资源互相隔离。
租户:可以是企业客户、独立项目、终端用户分组。
核心目标:共享服务代码,降低运维成本;同时严格隔离租户数据、控制各租户 API 配额,防止跨租户信息泄露。
三种多租户架构对比
| 方案 | 隔离级别 | 开发成本 | 适用场景 |
|---|---|---|---|
| 共享数据库,共享表(行级隔离) | 低(代码隔离) | 低 | SaaS 中小客户,绝大多数场景 |
| 共享数据库,独立租户表 | 中 | 中 | 中型客户,需要单独数据归档 |
| 独立数据库(一租户一库) | 高 | 高 | 大型企业、强合规、数据必须物理隔离 |
推荐方案:共享库 + 共享表,通过 tenant_id 行级隔离,平衡成本与安全性,也是 Claude Agent SDK SaaS 最常用方案。
前置准备
- Python3.10+ / Node.js18+
- SDK:
anthropic/@anthropic-ai/sdk - 数据库:MySQL / PostgreSQL,Redis(配额、缓存)
- 基础:会话持久化、错误重试、并发控制(前面章节内容)
核心架构设计
核心租户维度
tenant_id:租户唯一标识(UUID),所有业务表必须携带 tenant_iduser_id:租户下的子用户,一个租户可多个用户- API Key 策略:两种模式
- 平台统一持有 Anthropic API Key,平台侧做配额分发(推荐)
- 租户自行填入自己的 Anthropic API Key,平台仅做代理转发(适合企业客户自带密钥)
数据流
- 租户用户发起请求,请求头携带
tenant_id - 服务校验租户状态、额度、权限
- 读取该租户的会话历史(带 tenant_id 过滤)
- 调用 Claude SDK 执行Agent任务(工具调用/子代理/流式)
- 保存消息、token消耗、日志,所有记录写入时自动带上 tenant_id
- 返回结果,禁止读取其他租户任何数据
数据库表设计(共享库共享表,MySQL)
租户表 tenant
CREATE TABLE tenant (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
tenant_id VARCHAR(64) NOT NULL UNIQUE COMMENT '租户唯一UUID',
tenant_name VARCHAR(128),
status TINYINT NOT NULL DEFAULT 1 COMMENT '0禁用,1正常',
max_rpm INT DEFAULT 10 COMMENT '租户最大请求并发RPM',
max_token_month BIGINT DEFAULT 1000000 COMMENT '月度token限额',
self_api_key TEXT NULL COMMENT '租户自备Anthropic Key,可为空',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
租户会话表 agent_session(重点,增加tenant_id)
CREATE TABLE agent_session (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
session_id VARCHAR(64) NOT NULL,
tenant_id VARCHAR(64) NOT NULL,
user_id VARCHAR(64),
messages JSON NOT NULL,
total_input_tokens INT DEFAULT 0,
total_output_tokens INT DEFAULT 0,
status TINYINT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_tenant_session (tenant_id, session_id)
);
租户用量统计表 tenant_usage
CREATE TABLE tenant_usage (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
tenant_id VARCHAR(64) NOT NULL,
stat_date DATE NOT NULL,
input_tokens BIGINT DEFAULT 0,
output_tokens BIGINT DEFAULT 0,
request_count INT DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_tenant_date (tenant_id, stat_date)
);
关键:查询会话时,必须同时带上 tenant_id + session_id,不能只用 session_id 查询,防止越权读取其他租户会话。
租户API密钥两种模式代码示例(Python)
模式1:平台统一API Key(平台管控配额)
所有租户共用平台的 Anthropic Key,平台内部按租户做限流与计费
import os from anthropic import Anthropic# 全局平台客户端
platform_client = Anthropic(api_key=os.getenv("PLATFORM_ANTHROPIC_KEY"), timeout=20)def get_tenant_agent_client(tenant_id: str):
# 平台统一密钥,直接返回全局client
return platform_client
模式2:租户自带API Key(企业客户Bring your own key)
每个租户使用自己的 Anthropic API Key,平台不接触租户模型计费
from anthropic import Anthropic
# 伪代码:从数据库读取租户密钥
def get_tenant_agent_client(tenant_id: str):
tenant_api_key = get_tenant_api_key_from_db(tenant_id)
if not tenant_api_key:
raise Exception("租户未配置API Key")
return Anthropic(api_key=tenant_api_key, timeout=20)
租户资源隔离与限流(Redis实现)
多租户最容易踩坑:A租户高并发请求,占用全部API配额,影响B租户。
需要租户级独立限流:
- 全局总RPM限制(Anthropic API Key 总限额)
- 每个租户单独RPM上限(在tenant表配置max_rpm)
- 月度token消耗上限,超过直接拒绝请求
Redis 限流伪代码:
# 校验租户是否超出RPM限额
def check_tenant_rpm(tenant_id: str, max_rpm: int) -> bool:
key = f"tenant:rpm:{tenant_id}"
# 计数器+1,过期60秒
count = redis.incr(key)
if count == 1:
redis.expire(key, 60)
return count <= max_rpm
工具调用的租户隔离要点
工具(文件读写、数据库查询、MCP调用)是多租户高危点!
- 租户文件目录隔离:每个租户独立工作目录,路径强制前缀绑定tenant_id,禁止跨目录访问,防止路径穿越读取其他租户文件
- 自定义工具入参校验:所有路径参数做白名单校验,强制限定租户根目录
- MCP服务隔离:
- 轻量场景:MCP实例按租户会话隔离
- 成本优化:共享MCP服务,但工具操作上下文必须带上tenant_id做权限校验
示例:租户文件根目录
./tenant_workspace/{tenant_id}/
工具收到文件路径,自动拼接租户根目录,不允许 ../ 向上跳转。
租户子代理隔离
子代理并行开发章节中,子代理会话同样必须绑定 tenant_id,持久化存入 agent_session 表:
- 子代理生成的消息、tool_use/tool_result 全部归属租户
- 子代理的并发额度占用租户自身RPM配额
- 禁止子代理读取其他租户会话、文件、数据
安全与权限规范(重点)
- 永远不要省略 tenant_id 条件:所有SQL查询、更新、删除必须带上
tenant_id,否则会出现越权漏洞 - 租户API Key加密存储:租户自备的Anthropic Key,数据库中AES加密存储,禁止明文保存
- 提示词隔离:租户自定义系统提示词、CLAUDE.md风格规则,单独存在租户配置,互不干扰
- 审计日志:每一条请求记录 tenant_id、session_id、token消耗、工具调用记录,方便溯源
- 软删除:租户注销不直接删除数据,先标记禁用,满足合规备份要求
租户计量与计费
- 每次SDK调用完成,提取
usage里面input_tokens、output_tokens - 写入
tenant_usage按天聚合统计 - 可配置:按token计费、包月度额度套餐
- 告警:租户token用量达到阈值(例如80%)发送预警;达到上限直接拦截新请求
获取token消耗示例 Python
resp = client.messages.create(...)
input_tokens = resp.usage.input_tokens
output_tokens = resp.usage.output_tokens
# 写入租户用量统计
save_tenant_token_usage(tenant_id, input_tokens, output_tokens)
多租户常见坑
- ❌ 只使用session_id查询会话,不带tenant_id,越权漏洞
- ❌ 租户文件目录不隔离,路径穿越读取他人文件
- ❌ 全局统一限流,没有租户独立配额,大租户挤占小租户资源
- ❌ 租户API Key明文存储,密钥泄露风险
- ❌ 子代理、工具调用不记录tenant_id,审计日志无法区分租户
最佳实践
- 优先采用「共享数据库,行级租户隔离」架构,快速落地SaaS。大客户单独提供独立数据库方案。
- 分层限流:全局API Key总限额 + 租户独立RPM + 租户月度token上限三重防护。
- 所有租户资源(会话、文件、配置、用量)都绑定 tenant_id。
- 区分两种密钥模式:平台密钥用于标准SaaS;租户自带密钥用于企业私有化客户。
- 增加租户开关,可一键禁用租户,紧急情况下关停租户请求。
小结
Claude Agent SDK多租户设计核心:tenant_id行级隔离 + 租户独立配额管控 + 工具层资源隔离。
共享库行隔离是首选方案,同时做好token用量统计、密钥加密、审计日志。工具调用和文件操作是多租户安全高危区,必须严格做路径与权限隔离。
0 条笔记