系统架构
NOLUX 采用现代化的云原生多租户 SaaS 架构,兼顾高性能、数据隔离与弹性扩展。本文档面向技术人员和架构师,详细介绍系统的分层设计。
十层架构总览
┌─────────────────────────────────────────────────────┐
│ L10 客户端层 React 19 + Ant Design 5 (暗色主题) │
├─────────────────────────────────────────────────────┤
│ L9 CDN / 网关层 Nginx + 阿里云 CDN │
├─────────────────────────────────────────────────────┤
│ L8 API 网关层 FastAPI + JWT 认证 + 限流 │
├─────────────────────────────────────────────────────┤
│ L7 中间件层 Auth → Tenant → RBAC → Handler │
├─────────────────────────────────────────────────────┤
│ L6 业务服务层 六大核心模块业务逻辑 │
├─────────────────────────────────────────────────────┤
│ L5 AI 服务层 Agent 框架 + 模型路由 + 用量计量 │
├─────────────────────────────────────────────────────┤
│ L4 数据访问层 SQLAlchemy 2.0 异步 ORM │
├─────────────────────────────────────────────────────┤
│ L3 数据存储层 PostgreSQL + Redis + OSS │
├─────────────────────────────────────────────────────┤
│ L2 基础设施层 阿里云 ECS / RDS / Redis / OSS │
├─────────────────────────────────────────────────────┤
│ L1 可观测层 日志 + 指标 + 链路追踪 │
└─────────────────────────────────────────────────────┘多租户 Schema 隔离
NOLUX 采用 PostgreSQL Schema 级别的多租户隔离策略,在安全性和运维效率之间取得最佳平衡:
设计原则
- 公共 Schema(
public):存储租户元数据、用户认证信息、订阅计划、全局配置 - 租户 Schema(
tenant_{slug}):每个租户独立的 Schema,存储该租户的全部业务数据 - 自动创建:新租户注册时,系统自动创建 Schema 并执行 migration
- 完全隔离:租户 A 无法查询或访问租户 B 的任何数据
sql
-- 租户 Schema 结构示例
public.tenants -- 租户注册表
public.users -- 用户表(关联租户)
public.subscriptions -- 订阅信息
tenant_brand_x.products -- 品牌 X 的商品数据
tenant_brand_x.orders -- 品牌 X 的订单数据
tenant_brand_x.ad_campaigns -- 品牌 X 的广告计划
tenant_brand_y.products -- 品牌 Y 的商品(完全隔离)Schema 切换机制
请求处理时,TenantMiddleware 从 JWT 令牌中提取 tenant_id,通过 SET search_path 切换到对应的租户 Schema:
python
# 中间件自动设置租户上下文
request.state.tenant_schema = f"tenant_{tenant_slug}"
# 数据库会话自动切换 search_path
await session.execute(text(f"SET search_path TO {schema}"))中间件栈
NOLUX 的中间件按照严格的顺序执行,确保认证、租户识别和权限校验的正确性:
请求进入
│
▼
AuthMiddleware ← 验证 JWT,提取用户信息
│
▼
TenantMiddleware ← 识别租户,切换 Schema
│
▼
RBACMiddleware ← 校验角色权限和数据范围
│
▼
路由处理器 ← 执行业务逻辑顺序重要
Starlette 中间件采用"后添加先执行"的机制。代码中的注册顺序是 RBAC → Tenant → Auth,但实际执行顺序是 Auth → Tenant → RBAC。
RBAC 权限体系
NOLUX 实现了五级角色权限控制(Role-Based Access Control):
角色层级
| 角色 | 说明 | 数据范围 |
|---|---|---|
super_admin | 平台超级管理员 | 全局(无限制) |
tenant_admin | 租户管理员 | 本租户全部数据 |
manager | 部门管理者 | 本部门及下级数据 |
operator | 运营人员 | 所属组织节点数据 |
viewer | 只读用户 | 所属节点只读权限 |
权限格式
权限采用 {resource}:{action} 格式,支持领域特定的操作类型:
connector:manage -- 连接器管理
campaign:create -- 创建广告计划
campaign:approve -- 审批广告计划
report:export -- 导出报告
ai:configure -- AI 模型配置超级管理员拥有通配符权限 *,在权限检查时直接放行。
数据范围控制
通过 PostgreSQL 递归 CTE 查询组织树,确定用户的数据可见范围:
org_scope = None:超级管理员,无过滤org_scope = {org_ids}:仅可见指定组织节点及其子节点的数据org_scope = set():空集,无数据访问权限
订阅门控(Subscription Gate)
系统通过订阅等级控制功能可用性:
python
# 功能门控示例
@require_subscription(tier="growth")
async def byom_config(request):
"""仅 Growth 及以上方案可使用 BYOM 功能"""
...| 功能 | Starter | Growth | Enterprise | Custom |
|---|---|---|---|---|
| 全渠道引擎 | 2 连接器 | 10 连接器 | 无限 | 无限 |
| AI Autopilot | 基础 | 完整 | 完整 | 定制 |
| BYOM 自带模型 | - | 支持 | 支持 | 支持 |
| ChatBI | - | 基础 | 完整 | 定制 |
| 数据导出 (DaaS) | - | - | 支持 | 支持 |
| API 调用配额 | 1K/日 | 10K/日 | 100K/日 | 无限 |
AI 服务层
模型路由
AI Router 根据功能类型和租户配置,动态选择最优的 AI 模型提供商:
请求 → AI Router → 检查租户 BYOM 配置
→ 无自定义:使用默认通义千问
→ 有自定义:路由到租户指定模型
→ 用量计量 → 返回结果用量计量
每次 AI 调用都经过 Metering 层记录:
- Token 消耗量(输入/输出分别计量)
- 调用次数
- 响应延迟
- 关联的租户和用户
技术栈详情
| 层级 | 技术选型 | 说明 |
|---|---|---|
| 前端框架 | React 19 + Vite | SPA 单页应用,HMR 热更新 |
| UI 组件库 | Ant Design 5 | Cyber-Business 暗色主题定制 |
| 可视化 | ECharts 5 | 图表、热力图、仪表盘 |
| 后端框架 | FastAPI 0.115+ | 异步高性能 API 服务 |
| ORM | SQLAlchemy 2.0 | 异步 ORM,支持 Schema 切换 |
| 数据库 | PostgreSQL 16 | 多 Schema 租户隔离 |
| 缓存 | Redis 7 | 会话缓存、限流、实时数据 |
| 对象存储 | 阿里云 OSS | 报表、图片等静态资源 |
部署架构
┌─────────────┐
│ 阿里云 CDN │
└──────┬──────┘
│
┌──────▼──────┐
│ Nginx │
│ (反向代理) │
└──────┬──────┘
│
┌────────────┼────────────┐
│ │ │
┌─────▼─────┐ ┌───▼───┐ ┌─────▼─────┐
│ 前端静态 │ │ API │ │ WebSocket │
│ 资源服务 │ │ 服务 │ │ 服务 │
└───────────┘ └───┬───┘ └───────────┘
│
┌─────────┼─────────┐
│ │ │
┌─────▼───┐ ┌──▼──┐ ┌───▼────┐
│ PostgreSQL│ │Redis│ │阿里云OSS│
└─────────┘ └─────┘ └────────┘