SaaS架构:多租户、数据隔离与计费
SaaS架构:多租户、数据隔离与计费
SaaS系统架构概览
SaaS(Software as a Service)是软件即服务的模式,需要支持多租户共享应用实例。核心挑战是多租户隔离、数据安全、按需计费。
SaaS系统架构:
接入层:租户路由、身份认证、权限控制
业务层:
- 租户管理:租户注册、配置、配额
- 数据隔离:数据存储、访问控制、备份恢复
- 计费服务:订阅管理、用量计量、账单生成
- 资源管理:资源分配、扩缩容、配额控制
数据层:MySQL(共享/独立)、Redis、对象存储
基础设施:Kubernetes、服务网格、监控告警
多租户架构设计
多租户是SaaS的核心,需要在共享资源和租户隔离之间找到平衡。
# 租户管理服务
class TenantService:
def __init__(self):
self.tenant_repo = TenantRepository()
self.config_service = TenantConfigService()
def create_tenant(self, tenant_info):
"""创建租户"""
# 1. 创建租户记录
tenant = Tenant(
id=generate_tenant_id(),
name=tenant_info.name,
plan=tenant_info.plan,
status='ACTIVE',
create_time=time.time()
)
self.tenant_repo.save(tenant)
# 2. 初始化租户配置
self.config_service.init_tenant_config(tenant.id, tenant_info.plan)
# 3. 分配资源
self.allocate_resources(tenant)
# 4. 初始化租户数据
self.init_tenant_data(tenant.id)
return tenant
def allocate_resources(self, tenant):
"""分配资源"""
# 根据套餐分配资源
plan_resources = {
'basic': {'storage': 10, 'users': 10, 'api_calls': 1000},
'pro': {'storage': 100, 'users': 100, 'api_calls': 10000},
'enterprise': {'storage': 1000, 'users': 1000, 'api_calls': 100000},
}
resources = plan_resources.get(tenant.plan, plan_resources['basic'])
# 保存资源配额
self.save_resource_quota(tenant.id, resources)
数据隔离方案
数据隔离是SaaS的关键,需要根据安全要求和成本考虑选择合适的隔离方案。
// 数据隔离服务
@Service
public class DataIsolationService {
@Autowired
private DataSourceRouter dataSourceRouter;
@Autowired
private TenantContext tenantContext;
// 获取租户数据源
public DataSource getTenantDataSource() {
String tenantId = tenantContext.getTenantId();
return dataSourceRouter.route(tenantId);
}
// 执行租户查询
public <T> List<T> executeTenantQuery(String sql, Class<T> resultType) {
// 1. 获取租户数据源
DataSource ds = getTenantDataSource();
// 2. 注入租户过滤条件
String tenantSql = injectTenantFilter(sql, tenantContext.getTenantId());
// 3. 执行查询
return jdbcTemplate.query(ds, tenantSql, resultType);
}
// 注入租户过滤条件
private String injectTenantFilter(String sql, String tenantId) {
// 自动添加租户ID过滤
if (sql.contains("WHERE")) {
return sql + " AND tenant_id = '" + tenantId + "'";
} else {
return sql + " WHERE tenant_id = '" + tenantId + "'";
}
}
}
// 数据源路由器
@Component
public class DataSourceRouter {
private final Map<String, DataSource> dataSources = new HashMap<>();
@PostConstruct
public void init() {
// 加载所有租户数据源
List<Tenant> tenants = tenantRepository.findAll();
for (Tenant tenant : tenants) {
dataSources.put(tenant.getId(), createDataSource(tenant));
}
}
public DataSource route(String tenantId) {
return dataSources.computeIfAbsent(tenantId, this::createTenantDataSource);
}
private DataSource createTenantDataSource(Tenant tenant) {
// 根据租户配置创建数据源
HikariConfig config = new HikariConfig();
config.setJdbcUrl(tenant.getDbUrl());
config.setUsername(tenant.getDbUsername());
config.setPassword(tenant.getDbPassword());
config.setMaximumPoolSize(10);
return new HikariDataSource(config);
}
}
计费系统设计
计费系统是SaaS的商业模式核心,需要支持多种计费模式和准确的用量计量。
# 计费服务
class BillingService:
def __init__(self):
self.usage_meter = UsageMeter()
self.billing_repo = BillingRepository()
self.payment_service = PaymentService()
def record_usage(self, tenant_id, metric_type, quantity):
"""记录用量"""
# 1. 记录用量
usage = UsageRecord(
tenant_id=tenant_id,
metric_type=metric_type,
quantity=quantity,
timestamp=time.time()
)
self.usage_meter.record(usage)
# 2. 检查配额
quota = self.check_quota(tenant_id, metric_type)
if quantity > quota.remaining:
raise QuotaExceededError()
def generate_invoice(self, tenant_id, billing_period):
"""生成账单"""
# 1. 计算用量费用
usage_charges = self.calculate_usage_charges(tenant_id, billing_period)
# 2. 获取订阅费用
subscription_charge = self.get_subscription_charge(tenant_id)
# 3. 生成账单
invoice = Invoice(
tenant_id=tenant_id,
billing_period=billing_period,
usage_charges=usage_charges,
subscription_charge=subscription_charge,
total_amount=usage_charges + subscription_charge,
status='PENDING'
)
self.billing_repo.save_invoice(invoice)
return invoice
def calculate_usage_charges(self, tenant_id, billing_period):
"""计算用量费用"""
# 获取套餐价格
plan = self.get_tenant_plan(tenant_id)
pricing = self.get_pricing(plan)
# 计算各指标费用
total = 0
for metric_type, price_per_unit in pricing.items():
usage = self.usage_meter.get_usage(tenant_id, metric_type, billing_period)
total += usage * price_per_unit
return total
租户配置管理
每个租户可能有不同的配置需求,需要支持灵活的配置管理。
// 租户配置服务
@Service
public class TenantConfigService {
@Autowired
private ConfigRepository configRepo;
@Autowired
private CacheManager cacheManager;
// 获取租户配置
public TenantConfig getTenantConfig(String tenantId, String configKey) {
// 1. 尝试从缓存获取
String cacheKey = "config:" + tenantId + ":" + configKey;
TenantConfig cached = cacheManager.get(cacheKey);
if (cached != null) {
return cached;
}
// 2. 从数据库获取
TenantConfig config = configRepo.findByTenantIdAndKey(tenantId, configKey);
// 3. 如果租户没有配置,使用默认配置
if (config == null) {
config = getDefaultConfig(configKey);
}
// 4. 缓存结果
cacheManager.put(cacheKey, config, 3600);
return config;
}
// 更新租户配置
public void updateTenantConfig(String tenantId, String configKey, Object value) {
// 1. 更新数据库
configRepo.upsert(tenantId, configKey, value);
// 2. 清除缓存
String cacheKey = "config:" + tenantId + ":" + configKey;
cacheManager.evict(cacheKey);
// 3. 通知配置变更
notifyConfigChange(tenantId, configKey, value);
}
}
SaaS平台监控
SaaS平台需要监控租户级别的指标,支持租户隔离和问题定位。
SaaS监控体系:
租户级别监控:
- 资源使用率(CPU、内存、存储)
- API调用量和响应时间
- 业务指标(活跃用户、数据量)
- 计费指标(用量、费用)
平台级别监控:
- 整体可用性
- 资源利用率
- 性能指标
- 安全事件
告警策略:
- 资源使用率超过阈值
- API响应时间超标
- 配额即将用尽
- 安全异常检测
数据隔离:
- 租户数据访问审计
- 租户间资源隔离
- 租户配置隔离
- 租户日志隔离