JVS-Rules在多租户SaaS系统中的权限与规则隔离设计
摘要SaaS系统必须保证不同租户的数据与配置严格隔离。规则引擎作为业务决策的核心组件其租户隔离设计直接影响系统的安全性与可扩展性。本文以JVS-Rules为例详细阐述其在多租户场景下的规则隔离方案包括租户ID绑定、元数据隔离、规则执行上下文、性能优化及数据权限控制并提供架构图与代码示例。1. 多租户规则隔离的挑战在多租户SaaS系统中每个租户可能有完全不同的业务规则折扣、审批流程、风控阈值。规则引擎需要满足数据隔离租户A的规则不能被租户B看到或执行。配置独立每个租户可独立管理自己的决策表、规则流互不影响。性能可扩展租户数量增加时规则查找与执行不应线性下降。安全合规租户间禁止跨租户数据泄露。2. JVS-Rules的多租户架构JVS-Rules采用“共享引擎实例租户级规则仓库”的架构text┌─────────────────────────────────────────────┐ │ JVS-Rules 引擎实例 │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 租户A │ │ 租户B │ │ 租户C │ │ │ │ 规则缓存 │ │ 规则缓存 │ │ 规则缓存 │ │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ └────────────┼────────────┘ │ │ ↓ │ │ 规则仓库按tenant_id分表/分区 │ └─────────────────────────────────────────────┘核心设计点租户识别每个API请求携带租户IDJWT或Header。规则存储数据库所有规则表包含tenant_id字段并建立复合索引。规则缓存按租户ID隔离的本地缓存Caffeine/Redis。执行隔离规则编译后的Rete网络按租户独立存储避免跨租户影响。3. 数据库隔离设计采用共享表租户ID区分方案适合租户数量10000的SaaSsql CREATE TABLE decision_table ( id VARCHAR(32) PRIMARY KEY, tenant_id VARCHAR(32) NOT NULL, name VARCHAR(128), ... INDEX idx_tenant (tenant_id) ); CREATE TABLE decision_rule ( id VARCHAR(32) PRIMARY KEY, table_id VARCHAR(32), tenant_id VARCHAR(32) NOT NULL, ... );所有查询自动加上WHERE tenant_id ?条件通过MyBatis Plus拦截器实现。4. 规则编译与缓存隔离java Component public class TenantRuleEngine { private final MapString, RuleSet tenantRuleCache new ConcurrentHashMap(); public ListRuleResult fire(String tenantId, String tableName, MapString, Object facts) { RuleSet ruleSet tenantRuleCache.computeIfAbsent(tenantId _ tableName, key - loadRuleSet(tenantId, tableName)); return ruleEngine.fire(ruleSet, facts); } private RuleSet loadRuleSet(String tenantId, String tableName) { // 从数据库加载该租户的决策表编译为RuleSet DecisionTable table decisionTableMapper.selectByTenantAndName(tenantId, tableName); return DecisionTableCompiler.compile(table); } }缓存失效策略当租户修改规则时发送MQ消息或直接清除对应租户的缓存条目。5. 规则执行时的上下文安全规则脚本中可能引用租户特定的数据源或服务。需要确保脚本只能访问授权资源groovy // 规则脚本示例租户A def amount fact.order.amount def vipThreshold tenantConfigService.getConfig(vip_threshold) // 租户级配置 if (amount vipThreshold) { result.discount 0.2 } 为防止脚本跨租户访问可在脚本沙箱中注入租户ID校验 java // 脚本执行前绑定租户上下文 ThreadLocalString currentTenant new ThreadLocal(); currentTenant.set(tenantId); // 脚本中通过工具类获取租户ID并校验任何数据库查询都带上该ID6. 性能优化优化点实现方式规则预编译租户首次请求时编译并缓存后续直接使用租户级缓存隔离使用Caffeine的CacheBuilder为每个租户独立缓存避免大租户占满内存数据库连接池租户信息通过注解传递MyBatis插件自动注入租户ID避免SQL拼接开销批量规则执行支持批量事实Facts传入减少网络往返压力测试100租户每租户50条规则并发50命中缓存时P99延迟8ms。缓存未命中需加载编译P99延迟50ms。7. 数据权限的进一步扩展规则引擎除了规则隔离还可能需要控制规则执行后返回的数据范围。例如租户A下的不同部门只能查看本部门的数据。JVS-Rules支持在规则动作中调用数据权限服务对结果集进行过滤。8. 总结JVS-Rules的多租户设计兼顾了隔离性、性能与易用性。通过租户ID绑定、缓存隔离、脚本沙箱等机制实现了安全、高效的SaaS级规则引擎。对于正在构建SaaS产品的团队这套方案具有较高的参考价值。免费体验Demohttps://rules.bctools.cn/详情了解JVS官网-快速开发平台|JVS低代码开发平台标签#规则引擎 #多租户 #SaaS #JVS-Rules