3. ThingWorx多租户架构解析

ThingWorx 的多租户能力并不是一个单独的开关,而是由“租户边界 + 资源归属 + 权限作用域”三者共同构成的运行模型。理解这一模型的关键,是先分清哪些对象属于租户私有、哪些对象由平台共享,以及平台在请求进入时如何判定当前请求应落在哪个租户上下文中。

一、租户在 ThingWorx 中的真实含义

在 ThingWorx 中,租户(Tenant)通常对应一个独立的业务组织或客户环境。它不是一个简单的“用户分组”,而是一个带有独立命名空间、独立数据存储路径和独立权限边界的逻辑实例。每个租户拥有自己的 Thing、ThingTemplate、ThingShape、DataShape、Mashup、用户、用户组、应用程序密钥以及持久化数据表。平台通过租户标识(Tenant ID 或组织标识)将这些对象在逻辑上隔离,使不同租户即使使用相同的实体名称,也不会互相覆盖或互相访问。

需要特别注意的是,ThingWorx 的多租户实现属于“共享数据库、共享应用、逻辑隔离”模式,而不是每个租户一套独立进程或独立数据库。这意味着隔离的可靠性高度依赖平台在每次请求中正确注入租户上下文,并在数据访问层强制附加租户过滤条件。

二、租户隔离的三个层面

租户隔离在 ThingWorx 中至少体现在三个层面,缺一不可:

  • 身份隔离:用户、用户组、应用程序密钥均归属于某个租户。登录时,平台根据用户所属组织确定其租户上下文,后续所有权限判定都在该上下文内进行。
  • 模型隔离:Thing、ThingTemplate、Mashup 等建模对象按租户分区存储。同名实体在不同租户下是不同对象,跨租户引用默认不可见。
  • 数据隔离:流(Stream)、值流(ValueStream)、数据表(DataTable)等持久化数据在写入时绑定租户标识,查询时由平台自动附加租户过滤条件,防止越权读取。
如果自定义服务中直接使用底层 SQL 或绕过平台实体服务访问数据,必须自行保证租户过滤条件,否则会破坏平台默认的隔离机制。

三、共享资源与独立资源的划分

多租户架构中,资源并非全部私有。ThingWorx 将资源划分为共享资源与独立资源两类,划分依据是“该资源是否允许跨租户复用”。

资源类型归属典型对象跨租户可见性
独立资源租户私有Thing、Mashup、用户、DataTable、Stream仅本租户可见
共享资源平台级系统 ThingTemplate、内置 DataShape、平台扩展、系统用户组所有租户可引用
可授权共享租户私有但可显式授权被授予“可见性”的实体、共享 Mashup按授权范围可见

共享资源的存在是为了避免每个租户重复定义基础模型,降低平台维护成本;独立资源的存在则是为了保证业务数据与业务模型的边界清晰。实际项目中,最常见的错误是把本应私有的业务 Thing 放到了共享模板层,导致一个租户的修改影响其他租户。

四、多租户在 ThingWorx 中的实现方式

ThingWorx 的多租户实现可以概括为“请求进入 → 解析租户 → 注入上下文 → 权限判定 → 数据过滤”这条链路。下图展示了这一实现方式的核心结构:

ThingWorx 多租户请求处理与资源隔离链路 客户端请求 含租户标识 / 凭证 租户解析 Tenant ID → 上下文 权限判定 用户组 / 可见性 数据访问过滤 自动附加租户条件 租户 A 独立资源 Thing / Mashup 用户 / 用户组 DataTable Stream / ValueStream 隔离规则:同名实体互不可见 数据查询自动附加 Tenant A 条件 租户 B 独立资源 Thing / Mashup 用户 / 用户组 DataTable Stream / ValueStream 隔离规则:同名实体互不可见 数据查询自动附加 Tenant B 条件 平台共享资源:系统模板 / 内置 DataShape / 平台扩展

从图中可以看出,租户 A 与租户 B 各自拥有独立的 Thing、用户、数据表与流,彼此不可见;而系统模板、内置 DataShape 等平台级对象位于共享层,两个租户都可以引用,但不能修改其平台定义。请求进入后,平台先解析租户,再判定权限,最后在数据访问层自动附加租户过滤条件,从而保证隔离。

五、实现多租户时的关键操作

在实际部署中,多租户的落地通常围绕以下操作展开:

  1. 创建租户:在平台管理界面中新建组织或租户,指定租户标识、管理员账号和初始存储配额。
  2. 分配独立资源:在租户上下文中创建业务 Thing、Mashup、DataTable 等,确保它们归属于该租户而非平台共享层。
  3. 配置共享引用:若租户需要复用平台模板,通过“可见性”或“授权”方式将共享资源暴露给该租户,而不是复制一份。
  4. 验证隔离:使用租户 A 的用户登录,尝试访问租户 B 的实体名称,确认返回“未找到”或“无权限”,而不是返回数据。
  5. 检查数据过滤:在自定义服务中查询 DataTable 时,确认平台已自动附加租户条件;若使用底层查询,需手动加入租户字段。
一个实用的验证方法是:在两个租户下分别创建同名 Thing(例如 Device001),然后分别登录两个租户,确认各自只能看到自己的 Device001,且属性值互不影响。这能快速验证模型隔离与数据隔离是否生效。

六、常见误区与判断依据

多租户架构中最容易出问题的地方,是把“共享”与“独立”的边界搞混。判断一个资源应该放在哪一层,可以问三个问题:该资源是否被多个租户以相同方式使用?修改它是否会影响其他租户?它是否包含租户业务数据?如果答案分别是“是、否、否”,它可以放在共享层;否则应放在租户独立层。

另一个常见误区是认为“登录后平台会自动隔离一切”。实际上,平台只对通过标准实体服务访问的数据自动附加租户条件;一旦绕过实体服务直接操作数据库或外部系统,隔离责任就转移到了开发者身上。因此,在涉及自定义 SQL、外部 API 调用或文件存储时,必须显式传递并校验租户标识。

综上,ThingWorx 的多租户架构可以理解为:以租户为边界,以共享资源为复用基础,以独立资源为业务载体,以请求链路中的租户解析、权限判定和数据过滤为隔离保障。掌握这四者的关系,才能在后续的权限模型与治理实践中做出正确的资源归属决策。