2. ThingWorx单点部署架构剖析

在讨论高可用与灾备之前,必须先看清一个"最朴素"的ThingWorx部署长什么样。单点部署(Single-Node Deployment)是所有高可用方案的起点:它把ThingWorx平台的全部角色压缩到一台服务器上,结构简单、部署快、成本低,但也因此把系统可用性完全押注在单一硬件与单一进程栈上。理解它的拓扑、组件依赖和故障边界,才能判断"哪些环节值得冗余、哪些环节冗余了也没用"。

一、典型单机部署拓扑

一个可用的ThingWorx单机环境通常由四层构成:接入层、应用层、数据层和外部依赖层。接入层是Nginx或Apache反向代理,负责TLS终止、静态资源分发和请求转发;应用层是Tomcat承载的ThingWorx Platform Web应用(platform.war),内部运行着Composer、Mashup Builder、Thing/ThingTemplate引擎、事件与订阅处理、以及平台子系统(Platform Subsystem);数据层是PostgreSQL数据库,存放模型实体、用户、权限、配置与部分运行时数据;外部依赖层则包括文件存储(本地磁盘或挂载卷)、LDAP/SSO身份源、邮件服务、以及被集成的外部系统(如ERP、MES、OPC UA网关)。

请求路径是:客户端 → 反向代理(443)→ Tomcat(8080)→ ThingWorx运行时 → JDBC(5432)→ PostgreSQL。这条链路上任何一环中断,平台即不可用。下图给出单机拓扑与依赖关系。

ThingWorx 单机部署拓扑与依赖关系 客户端 浏览器 / 移动端 / API Nginx 反向代理 TLS终止 · 443→8080 Tomcat 9 · ThingWorx Platform Composer / Mashup 建模与UI引擎 Thing / 事件引擎 订阅 · 流处理 Platform Subsystem · 调度 · 日志 JVM 堆 · 线程池 · 连接池 PostgreSQL 13 模型实体 · 用户权限 · 配置 · 运行时数据 外部依赖(单点) 本地磁盘文件存储 · LDAP/SSO · 邮件 · OPC UA网关 JDBC 5432 文件/身份/集成 ⚠ 单点故障风险点(SPOF) Nginx 进程崩溃 → 全部入口不可达 Tomcat/JVM 宕机或 OOM → 平台整体不可用 PostgreSQL 单实例故障 → 数据不可读写,恢复依赖备份 本地磁盘损坏 → 文件存储与日志丢失,无法回放 主机硬件故障 → 全栈同时失效 外部身份源不可达 → 用户无法登录 无备用节点 → 恢复时间 = 硬件更换 + 重装 + 数据恢复

二、各组件角色与依赖关系

反向代理本身不保存业务状态,它的价值在于统一入口和TLS卸载,但一旦它成为唯一入口,就变成了新的单点。Tomcat是"有状态"的:JVM堆中缓存着会话、Thing实例、订阅关系和部分未落库的运行时数据,因此它不能像无状态Web节点那样随意重启。PostgreSQL是唯一持久化的真相来源,模型、权限、配置、历史数据都在这里,它的可用性直接决定平台能否恢复。文件存储常被忽视——Mashup上传的图片、扩展包、日志文件若只放在本地磁盘,节点重建后就无法还原。

依赖方向是单向的:应用依赖数据库,数据库不依赖应用;应用依赖外部身份源完成认证,但身份源故障时通常已有本地缓存或应急账号可兜底。理解这一点很重要——数据库和文件存储是"必须优先保护"的资产,而Tomcat和Nginx是"可以重建"的计算资源。

三、单点故障风险识别

把单机环境按"故障域"拆开,可以列出五类典型风险:

  • 进程级故障:Tomcat因内存泄漏或线程耗尽而假死,表现为HTTP 502/504,但主机仍在运行。这类故障重启进程即可恢复,但期间所有用户中断。
  • 数据库故障:PostgreSQL崩溃或磁盘写满,平台无法读写模型,Composer保存失败、Mashup加载报错。恢复依赖备份与WAL回放,RTO通常在小时级。
  • 主机级故障:电源、网卡、系统盘损坏,整机不可用。这是最严重的场景,因为没有第二台机器接管。
  • 存储级故障:本地磁盘RAID失效或挂载卷丢失,文件与日志不可访问,即使数据库完好也无法完整恢复。
  • 依赖级故障:LDAP、邮件、外部网关不可达,影响登录、告警和集成,但不一定导致平台整体宕机。
单机部署的RTO(恢复时间目标)通常等于"硬件更换 + 系统重装 + ThingWorx重部署 + 数据恢复"的总和,实际项目中常在4~24小时;RPO(恢复点目标)取决于备份频率,若每日全备,最坏情况会丢失近24小时数据。

四、从单机到高可用的演进路径

高可用不是一步到位,而是按"消除单点"的顺序逐步演进。合理的路径是:

  1. 数据层先行:把PostgreSQL改为主备流复制(Streaming Replication),配合Patroni或repmgr实现自动故障切换。这是收益最高的一步,因为数据是唯一不可重建的资产。
  2. 应用层无状态化:将ThingWorx会话外置到共享存储或数据库,使多个Tomcat节点可以并行运行,前面用负载均衡分发。此时需要处理会话粘滞或分布式会话。
  3. 接入层冗余:部署两个Nginx节点,用Keepalived VIP或云负载均衡对外提供统一入口,消除代理单点。
  4. 文件存储共享化:把本地磁盘替换为NFS、S3兼容对象存储或分布式文件系统,使任意节点都能访问同一份文件。
  5. 跨站点灾备:在异地部署数据库副本和应用节点,通过异步复制和DNS/GTM切换实现站点级容灾。

每一步都对应一个明确的故障域消除目标,而不是盲目堆机器。判断演进是否到位,可以问三个问题:数据库主库宕机后能否在分钟级切换?应用节点宕机后用户是否无感?文件存储是否与计算节点解耦?三个都答"是",才算真正跨过了单点阶段。

演进顺序建议遵循"数据 → 应用 → 接入 → 存储 → 站点"的优先级。先做应用双活而数据库仍是单点,等于把可用性瓶颈留在了最脆弱的地方,投入产出比很低。

单机部署的价值在于它是理解依赖关系的"最小完整样本"。看清了它的拓扑和故障边界,后续的高可用设计才有明确的靶心:不是让每个组件都变复杂,而是让每一个不可重建的资产都有冗余,让每一个可重建的组件都能被快速替换。