应用参考。 这是一个示例性架构和范围检查清单,并非经过验证的客户项目或经过测量的部署。技术方案、集成范围和交付内容将根据实际需求确定。
场景与约束
一个部署为多个客户组织提供服务的产品。决定一切的关键是隔离模型:使用带租户列的共享表、每个租户一个模式,还是每个租户一个数据库。未经审慎评估就默认选择某种方案,是这一类别中代价最高的错误,因为之后更改意味着迁移在线客户数据。
架构
层级与职责
| 层级 | 技术 | 负责内容 |
|---|---|---|
| Web | Next.js(营销页面和 SEO 使用 SSR,登录后使用 SPA) | 公共页面通过服务端渲染提升搜索可见性;已认证产品不需要 SSR,保持为客户端应用。 |
| API | Go + Gin,按请求解析租户 | 在任何处理程序运行前,从子域名或令牌中解析租户上下文,然后将其贯穿每次查询。 |
| 存储 | PostgreSQL,共享模式并按行进行租户范围限定 | 一个数据库,每个租户自有表都包含 tenant_id,在仓储层强制执行;在支持的情况下,再通过行级安全策略作为第二道防线。 |
| 缓存 | Redis,使用租户前缀键 | 用于会话、速率限制和热点配置。键前缀可以防止经典的缓存键冲突,避免一个租户的数据泄露给另一个租户。 |
| 计费 | Stripe 或区域性网关 | 在本地镜像保存订阅状态,使权益检查不依赖于实时调用支付服务商。 |
| 任务 | 携带租户上下文的队列工作进程 | 处理定时和异步工作;租户上下文随任务负载传递,而不是在执行时推断。 |
数据模型
下表包含其他所有部分所依赖的规则。这里出错,会把一个可运行的演示变成无法扩展的系统。
核心实体
| 实体 | 关键字段、关系与规则 |
|---|---|
| tenant | 包含套餐、状态、区域和功能开关的组织记录。每个租户自有表都包含 tenant_id,任何查询都不得省略该字段。 |
| user / membership | 一个用户可以属于多个租户,并且在每个租户中拥有不同角色,因此身份是全局的,而权限属于每个成员关系。将用户和成员关系建模为一张表,会使之后支持多组织变得不可能。 |
| role / permission | 权限授予角色,角色按成员关系分配,并且每次检查都在后端执行。前端隐藏只是展示层行为,绝不能作为强制措施。 |
| subscription / entitlement | 包含套餐、席位、周期和派生权益。功能访问读取本地权益,因此支付服务商中断不会导致客户无法使用产品。 |
| audit_log | 包含操作者、租户、操作、目标以及操作前后负载。支持安全审查和事件分析;应在实现前确定保留期限、访问权限和审计要求。 |
| tenant_config | 每个租户的设置、品牌配置和功能覆盖项,并按照已记录的优先级覆盖套餐默认值。 |
关键接口
承载业务规则的端点
| 端点 | 用途与并发说明 |
|---|---|
| POST /api/v1/auth/login | 验证身份,然后返回可用的租户成员关系;租户由用户明确选择,而不是根据上一次会话猜测。 |
| GET /api/v1/{resource} | 每个租户范围内的读取请求都通过注入 tenant_id 的仓储执行。范围限定集中在一个位置,因此任何处理程序都无法遗漏,这是跨租户数据泄露最常见的来源。 |
| POST /api/v1/webhooks/billing | 处理支付服务商 Webhook,以事件 ID 实现幂等,并更新本地订阅和权益状态。 |
| POST /api/v1/tenants/{id}/invite | 执行邀请流程,创建带有角色的成员关系,并按租户实施速率限制,以防止邀请滥用。 |
| GET /api/v1/audit | 提供带分页的租户范围审计查询,供租户管理员自助满足合规要求。 |
技术决策
- 有意选择带 tenant_id 的共享模式。 这种方案运营和迁移成本最低,适合大多数产品。如果客户合同要求物理隔离,同一代码库也可以运行专用部署;该路径应从一开始就设计好,而不是在销售谈判期间才发现。
- 在一个仓储层中强制执行租户范围限定。 依赖每位开发者记住添加 WHERE 子句,正是跨租户泄露发生的原因。将其集中管理,可以让开发者难以意外编写不安全的查询。
- 在本地镜像保存权益。 每次请求都检查支付服务商会增加延迟并形成硬依赖。本地镜像意味着服务商中断影响的是计费操作,而不是产品本身。
- 从首个版本开始记录审计日志。 事后补填审计历史是不可能的。应确认买方的审计要求,并从首个版本开始保留约定的历史记录。
- 仅对公共页面使用 SSR。 营销和文档页面需要搜索可见性;已认证产品不需要,强行为其使用 SSR 会增加成本而没有回报。
假设性设计目标
以下数据是假设性的容量规划示例,不代表经过测量的客户结果、经过验证的容量建议或 SLA。应在定义工作负载、设备、数据、硬件和第三方依赖后,设定项目专属的验收目标;在承诺生产目标前,通过试点和负载测试进行验证。
容量与性能目标
| 目标 | 数值与假设 |
|---|---|
| API 延迟 | 对于租户范围读取请求,p95 低于 250 ms,并确保正确的复合索引以 tenant_id 开头。 |
| 租户隔离 | 要求建立自动化测试套件,在每个端点上尝试跨租户访问,并在发生未授权访问时使构建失败。实现必须通过这些检查;本参考内容不构成已完成安全测试的证据。 |
| 入驻 | 新租户在数秒内完成配置,因为这只是创建一行记录和一条配置记录,而不是基础设施工作。 |
| 扩展 | 按一个 PostgreSQL 实例承载数千个租户的较低数量级进行规划;超过该规模后,路径是先使用只读副本,再按租户分片,提前规划但不仓促构建。 |
交付内容
- 仓库中的 Next.js 前端源代码、Go 后端源代码和管理面板源代码
- 已记录租户范围限定、索引和审计表的数据库模式,以及迁移历史
- 可在您的 CI 中运行的跨租户隔离测试套件
- 计费集成、Webhook 处理和权益文档
- Docker 和 Nginx 部署说明、环境配置、备份和恢复流程
为您的业务进行规划
上述模块是起点,而不是固定套餐。我们通常会将首个版本限定为一个核心工作流和一个管理工作流,然后根据真实使用情况显示的负载和边界情况进行扩展。发送范围明确的需求说明,我们会将其与此架构进行对照,并告知您目前还不需要哪些部分。
