外观
多租户与用量模式篇
目标:让集成方读懂 ATKONBASE 的多租户隔离模型,用
/v1/tenants/me/storage获取当前租户的存储用量与配额,按租户维度聚合二次计费,并理解 TRUSTED_DELEGATED 跨租户场景下用量归属语义。不在本篇范围:TRUSTED_DELEGATED 身份请求头的完整用法与 granteeId 解析(见 认证与身份双通道模式篇);容器级用量统计(见 容器模型与层级模式篇 §三
containers/stats);配额超限错误码(173008TENANT_QUOTA_EXCEEDED,触发于预签名直传与内容摄入,见文件上传链路模式篇);错误码完整码表(见错误码参考)。
本篇是集成拓扑 §TRUSTED_DELEGATED 的用量维度纵深,以及领域模型 中租户硬隔离机制的集成方视角说明。
多租户隔离(用前必读)
ATKONBASE 采用多租户硬隔离:所有内容资源(容器 / 文档 / 版本 / ACL / 字段值 / 分享等)均在租户作用域内,不同租户之间的数据相互隔离,任何 V1 API 调用都无法越界读写其他租户数据。
- 每个 API Client(
clientId)归属一个租户;token 中的tenantId由clientId在服务端解码,不可被集成方伪造或篡改。 - 租户过滤自动注入:V1 所有资源端点在查询层自动注入当前租户过滤,集成方无需也不应手动在请求里传
tenantId做隔离。
TRUSTED_DELEGATED 跨租户场景
在多租户 ISV 嵌入部署中,一个 ISV 应用可能为多个下游客户(每个客户是一个租户)各自持有独立凭据。此时:
- 集成方为每个租户持有对应
clientId/clientSecret,分别换 token 调用。 - 用量归属:
/v1/tenants/me/storage返回的是当前 token 所归属租户的用量;ISV 做聚合二次计费时,按租户分别调用、按tenantId对应自己客户汇总,不要用同一 token 调用后手动拆分。 - 弱通道(
X-Atk-Act-As-Source+X-Atk-Act-As-Source-Id)在跨租户场景下:被委派的外部用户必须归属当前 token 所在租户,平台会校验跨租户合法性——非当前租户的用户主张会被拒绝(HTTP 403)。
更多隔离模式细节见集成拓扑 §多租户隔离;委派头的完整规约见 认证与身份双通道模式篇。
关键事实
- 端点:
GET /v1/tenants/me/storage,所需 scope:client:storage:tenant:read。 - 返回值含 5 分钟级缓存延迟;
sampledAt字段为采样时刻 epoch 毫秒——不应视为实时强一致数据。 - 可选参数
dimension=physical:切换到物理用量(去重后实际占用字节);默认或传其他任何值均返回逻辑用量(不报错)。 quotaBytes=null表示该租户未设置存储配额上限(无限制);集成方做 UI 时需处理此 null 情形(不要直接做除法计算百分比)。
curl 示例
bash
# 逻辑用量(默认)
curl -X GET 'https://api.atkonbase.example.com/v1/tenants/me/storage' \
-H 'Authorization: Bearer ${accessToken}'
# 物理用量
curl -X GET 'https://api.atkonbase.example.com/v1/tenants/me/storage?dimension=physical' \
-H 'Authorization: Bearer ${accessToken}'期望响应(关键字段)
json
{
"code": 0,
"data": {
"tenantId": "T1000001",
"dimension": "logical",
"usageBytes": 104857600,
"logicalUsageBytes": 104857600,
"physicalUsageBytes": 89478485,
"documentCount": 320,
"versionCount": 540,
"quotaBytes": 10737418240,
"softLimitRatio": 0.8,
"enforced": false,
"sampledAt": 1748426400000
}
}| 字段 | 含义 |
|---|---|
tenantId | 当前租户 ID |
dimension | 本次返回的用量维度:logical(逻辑)/ physical(物理) |
usageBytes | 按 dimension 给出的对应口径用量(集成方展示给用户时用此字段) |
logicalUsageBytes | 逻辑用量 = 所有文档版本大小求和(含历史版本,不去重)——用户感知值 |
physicalUsageBytes | 物理用量 = 对象存储中去重后实际占用字节——对象存储实际计费参考 |
documentCount | 租户内文档总数(ACTIVE + ARCHIVED,不含 TRASHED) |
versionCount | 租户内版本总数 |
quotaBytes | 配额上限(字节);null 表示无限制 |
softLimitRatio | 软限阈值(0 ~ 1);usageBytes / quotaBytes ≥ softLimitRatio 时集成方可提示用户 |
enforced | 是否启用 hard-block(达配额时拒绝新写入);当前版本通常为 false |
sampledAt | 采样时刻 epoch 毫秒(5 分钟级缓存,不反映实时用量) |
ISV 二次计费要点
ATKONBASE 按租户硬隔离用量,ISV 嵌入模式下集成方可:
- 为每个下游客户开一个租户(对应一套
clientId/clientSecret)。 - 定期(如每小时 / 每日)用对应租户 token 调
/v1/tenants/me/storage,拿usageBytes按自己的计费模型折算。 - 按
tenantId与自己客户 ID 的映射表汇总,对客户做二次计费账单。
⚠️
logicalUsageBytes与physicalUsageBytes在有大量重复文件(相同内容多次上传)的租户中可能差距显著:逻辑量按每个版本独立计,物理量按去重后实际对象计。两者均正确——选哪个维度做计费基准应与商务条款一致。
常见坑
- ⚠️
sampledAt表示当前时间:sampledAt是采样时刻(可能滞后最多 5 分钟),不是请求时刻;高频轮询也不会提高实时性,用量数字不随每次请求重新计算。 - ⚠️
quotaBytes=null做除法计百分比:null 表示无限制;直接计算会 NaN / 空指针,集成方需先判 null 再做比例换算。 - ⚠️ 容器
totalSizeBytes累加代替租户用量:容器stats.totalSizeBytes是该容器子树的逻辑量;用多个容器累加与/tenants/me/storage结果不等(范围不同、时效不同、口径可能不同)。租户级存储计费应读本端点,不要用容器级累加。 - ⚠️ 跨租户共用一个 token:ISV 的不同下游客户是不同租户,必须各自持对应凭据换 token,共用一个 token 会让所有写操作归属到同一租户,且用量无法按客户区分。
不在本段范围
- 容器级用量统计(非租户级聚合)→ 容器模型与层级模式篇 §三
containers/stats - 配额超限(写入时的
173008 TENANT_QUOTA_EXCEEDED)→ 文件上传链路模式篇 - TRUSTED_DELEGATED 跨租户委派头的完整规约 → 认证与身份双通道模式篇
下一步
- 认证三种形态与 TRUSTED_DELEGATED 跨租户行为 → 认证与身份双通道模式篇
- 容器级子树用量(
containers/stats)→ 容器模型与层级模式篇 - V1 端点契约 + Try-it → 接口参考