SaaS多租户用CDN做资源隔离,核心思路是让CDN成为租户感知的边缘网关,通过缓存Key拆分、目录规约和鉴权前置三层手段,把静态资源的存储、加速和访问控制全部隔离到边缘节点上。
这是国内做SaaS平台最常踩的一个坑:应用层租户隔离做得挺完善,但CDN一接入就乱套张三的报表图片被李四的浏览器缓存命中,内测版本的前端JS被外部客户加载,问题根源在于多数CDN默认按URL缓存,而多租户场景下URL相同、内容不同,本文从实操角度拆解思路,讲透怎么在不让源站承压的前提下,把租户边界推到CDN节点上。
口径:SaaS多租户怎么用CDN把资源隔离开
先明确一个前提:CDN本身不是数据库,做不了行级粒度的权限隔离,能做的是缓存隔离和回源隔离,缓存隔离保证A租户的资源不会命中B租户的缓存;回源隔离保证CDN节点上没命中的请求,回源时能准确落到该租户对应的存储路径或鉴权服务上。
第一层:缓存Key改造,让每个租户的URL天然不同
这一步是地基,改不了缓存Key,后面全白搭。
常规做法是让CDN的缓存Key不再只取URL路径,而是组合以下三要素之一:
- 域名维度:每个租户分配独立子域名,如
tenant-a.yourcdn.com、tenant-b.yourcdn.com,改造简单,但域名数量多了以后证书申请和维护成本高,适合大客户单独定制。 - 路径前缀维度:URL改为
/tenant-a/static/js/app.js、/tenant-b/static/js/app.js,CDN按前缀自动分区,无需额外开发,是中小型SaaS平台性价比最高的方案。 - Header维度:URL保持统一,通过自定义Header如
X-Tenant-ID区分,这种方式对CDN的缓存Key自定义能力要求高,部分CDN厂商不支持,且浏览器静态请求携带自定义Header需要额外配置,不推荐在前端静态资源场景下用。
实际对接时,国内主流CDN控制台都有自定义缓存Key配置入口,以百度云CDN为例,路径在「缓存配置」→「缓存Key设置」里,勾选“根据请求参数生成缓存Key”或者“自定义缓存Key组成”,如果你的CDN不支持Header维度,优先做路径前缀维度。
第二层:缓存组与刷新粒度,控制隔离的爆炸半径
缓存Key把资源分开了,但刷新操作如果还按全站刷新,隔离就等于零。
多租户场景下必须建立缓存组概念,每个租户的资源绑定一个独立的缓存组,组与组之间刷新互不影响,具体配置分两步:
- 在CDN控制台创建多个刷新规则,按租户目录或域名关联。
- 通过API下发刷新任务时,带上租户标识,只刷新该租户对应的URL前缀。
这里有个很典型的坑:很多团队图省事,用通配符刷新整个目录,比如租户A上架了新版本前端代码,运维直接刷新/static/,结果租户B因为还没做灰度验证,缓存被提前冲掉,源站压力瞬间翻倍,行业共识是刷新粒度必须等于或小于隔离粒度,否则隔离策略形同虚设。
场景:SaaS资源隔离用CDN还是用OSS私有空间
很多团队会纠结,资源隔离到底放在对象存储层做,还是放在CDN层做,这两者不冲突,但侧重点完全不一样。
OSS私有空间方案:所有租户的静态资源上传到OSS,URL带上签名才能访问,CDN回源时也要带签名,优势是权限控制极严,适合合同、发票、订单导出文件等敏感数据,劣势是每次访问都要算签名,CDN缓存命中率低,回源压力大。
CDN隔离方案:用上文说的缓存Key拆分方式,CDN边缘节点通过回源鉴权插件校验租户身份,校验通过后放行并缓存,优势是命中率高,用户访问速度快;劣势是权限模型相对粗糙,不适合存放强敏感文件。
选型建议直接给结论:
| 资源类型 | 推荐方案 | 原因 |
|---|---|---|
| 前端JS/CSS/图片 | CDN缓存隔离 | 高频访问、无强敏感数据、需要极致加速 |
| 用户上传的合同/发票 | OSS私有空间+CDN鉴权回源 | 强敏感、需追溯、访问频率低 |
| 视频/音频大文件 | CDN缓存隔离+URL鉴权 | 体积大、可容忍缓存延迟、防盗链优先 |
做SaaS的团队要注意一个特别场景:多租户共享同一套前端代码,但不同租户的配置项不同,比如小程序H5商城,每个商家的主题色、运费模板、展示开关都不一样,这种场景建议把配置项做进JS/CDN缓存Key,用路径前缀区分,而不是在运行时动态拼装,否则边缘节点会频繁回源。
代价:CDN做多租户隔离的隐形开销与边界
想清楚代价再看思路,避免过度设计。
缓存容量与命中率的两难
按租户拆分缓存Key后,同一个资源被拆成多个缓存副本,假设平台有1000个租户,一个大小200KB的公共JS文件,之前用一份缓存,现在可能需要存1000份,边缘节点的存储成本会线性上升。
缓解手段有两个:
- 识别出真正“全局公共”的资源(比如Vue/React框架文件、公共组件库),单独划一个公共缓存区,不参与租户拆分。
- 对“大租户”和“小租户”设置不同的缓存过期时间,大租户资源频繁被访问,缓存时间可以适当拉长到72小时;小租户活跃度低,缓存时间缩短到24小时,避免占着空间不更新。
回源鉴权是隔离的最后一公里
CDN节点缓存未命中时,回源请求必须带上租户标识,否则源站无法判断该给哪份资源。
比较靠谱的做法是回源鉴权插件(即回源时在CDN边缘节点执行一段自定义鉴权逻辑):
- 请求进来时,CDN节点解析出租户ID(从路径或Header里取)。
- 边缘节点调用鉴权服务的API,校验该租户是否有权访问这个URL路径下的资源。
- 鉴权通过,CDN直接回源取资源并缓存;鉴权失败,返回403,不触发回源。
现在国内CDN厂商里,百度云、简米云、酷番云的CDN都提供边缘脚本或边缘计算能力,可以实现上述逻辑,如果用的是纯静态CDN服务,没有边缘脚本能力,那就只能退而求其次,在源站Nginx层做校验,但这样一来,每一次缓存未命中都会多一次鉴权往返,性能有损耗。
控制台与API的管理边界
多租户SaaS平台通常需要让客户自己在控制台查看流量报表、刷新缓存,但业务方自己也是租户,不能把CDN根账号给客户,合理做法是:
- 用CDN的子账号/访问控制(RAM/STS)能力给每个租户分配一个只读权限的子账户,仅开放“刷新缓存”和“查看统计”这两个Action。
- 把刷新和预热的API封装成自己的后端服务,由业务后端去调用CDN公开API,而不是向客户暴露AK/SK。
落地:业内常见隔离方案权衡与配置示例
不同体量的SaaS团队,做CDN隔离的路径不一样。
小型SaaS平台(租户量100以下)
直接用目录前缀隔离,不引入边缘脚本和复杂鉴权,后端给每个租户生成一个唯一ID,上传资源时存储路径强制写入租户ID,前端拼URL时带上,CDN侧只做一件事:把缓存Key改为“路径前缀+文件名”,这个方案开发量最小,一小时能上线。
# 源站Nginx配置示例:按租户目录分流
location /content/ {
rewrite ^/content/([^/]+)/(.)$ /storage/$1/$2 break;
proxy_pass http://internal-storage;
}
中型SaaS平台(租户量100-5000)
增加回源鉴权环节,租户ID从URL中提取,CDN边缘节点每个月会定期回源到鉴权服务换取短时令牌,后续直接按令牌判断资源是否可访问,推荐用百度云CDN的“URL鉴权”功能,配置在主域名下的目录级,只对/content/{tenant-id}/生效,公共资源路径不走鉴权。
SKIPPING这里有一个特别容易忽略的细节:鉴权字段要排除掉CDN的预加载/预热请求,很多团队的预热任务用的是内部固定UA,边缘节点鉴权时要把这类请求放行,否则预热永远失败。
大型或强合规SaaS平台(租户量5000以上)
这就要把所有租户的资源隔离纳入客户侧、平台侧、运维侧三端协同体系,执行更严的隔离策略:
- 客户侧:只暴露专属加速域名或专属目录,不让客户感知底层CDN。
- 平台侧:下发每个租户的缓存策略模板,新租户开通时自动绑定一套隔离配置,不允许人为修改。
- 运维侧:所有刷新任务经过消息队列,逐租户有序执行。
这个方案下,CDN不只是缓存层,已经变成了客户资源的“边缘入口网关”。
为什么你的SaaS平台需要重新审视CDN租户隔离
不少团队觉得“我有应用层隔离就够了”,但实际排查线上问题时,那些奇怪的“别人看到了我的文件”的故障报告,绝大多数都能追溯到CDN缓存没做租户拆分。
从架构演进角度看,早期SaaS平台租户量少,静态资源不多,源站直出也能扛住,随着租户和资源量上升,CDN加速成为刚需,这时如果隔离方案滞后,就会遇到一个尴尬局面:加CDN省了源站带宽钱,但引入了数据越权的风险,从成本侧看,在CDN层做隔离比在应用层做隔离更划算应用层每次请求都要跑一遍权限逻辑,而CDN边缘层鉴权后就直接响应了,计算压力被摊薄,从交付侧看,客户对“我们平台的资源是物理隔离的”这句话越来越敏感,虽然CDN隔离严格来说是逻辑隔离,但配合私有存储空间,已经能满足大多数SaaS客户的安全审查要求。
所以我的结论是:SaaS多租户用CDN做资源隔离不是要不要做的问题,而是早晚要做的问题,从目录前缀这种低成本方案起步,逐步演进到边缘鉴权、子账号权限收敛,这条路走通之后,多租户的静态资源加速就能放心往前推了。
Q&A:CDN多租户隔离的常见疑问
问:SaaS多租户用CDN做资源隔离会明显增加延迟吗?
不会,缓存Key拆分只是让CDN节点多存几份副本,命中缓存的响应速度与是否拆分无关,真正影响延迟的是回源鉴权环节,多一次请求到鉴权服务,大概增加10-30ms,如果业务对首屏时间极其敏感,可以考虑把鉴权结果在边缘节点做短时缓存(比如5秒),基本无感。
问:CDN资源隔离和多租户数据隔离是同一个概念吗?
不是,CDN级别的隔离只覆盖静态资源,比如图片、样式文件、下载包,真正的多租户数据隔离指的是数据库、对象存储里的业务数据,CDN隔离做得再好,也不能替代后端数据库的行级权限控制,两者是互补关系。
问:如果租户数量巨大,CDN缓存Key拆分会不会把源站拖垮?
会,这是个真实风险,上千个租户同时首次请求公共资源时,CDN节点分片都为空,会同时回源,形成“缓存击穿”,解决方法是区分“公共资源”和“租户私有资源”:公共资源走全站共享缓存Key,私有资源才走租户拆分Key,再配合源站层面的限流和队列,就能避开这个坑。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/794099.html


