管理中台篇五:Aspire、Gateway、DataWorker 与容器部署
管理中台要能本地开发,也要能部署交付。IIoT.CloudPlatform 不是一个单独 API 进程。它需要数据库、缓存、消息队列、迁移程序、HTTP API、网关、后台 worker 和前端一起运行。项目用 Aspire 组织本地开发运行环境,再用 compose 模板承接部署。
如果只把它当成一个后端服务,部署时容易漏掉数据库初始化、Redis、RabbitMQ、DataWorker、网关路径和前端静态资源。管理中台承载设备身份、配方版本、生产归档和后台查询,运行拓扑本身就是业务可靠性的一部分。

这张 Aspire 运行视图对应的是管理中台的运行拓扑。能看到多个资源和服务同时存在,而不是只有一个后端接口。这个视图证明了系统边界:HttpApi、Gateway、DataWorker、数据库、缓存和消息队列各自有位置。
AppHost 组织运行环境
IIoT.AppHost 里可以看到当前管理中台的核心运行资源:
- PostgreSQL/TimescaleDB:业务数据和时序/生产归档数据基础。
- Redis:缓存与部分运行态能力。
- RabbitMQ:事件总线和异步消息。
- MigrationWorkApp:迁移和初始化。
- HttpApi:业务接口和上传入口。
- Gateway:统一入口和路径转发。
- DataWorker:后台归档、Outbox、消息消费等异步工作。
- iiot-web:Vue 前端,承载登录、生产概览、人员、设备、配方、产能、日志、过站和权限页面。
这个结构把管理中台拆成了可观察的运行单元。数据库、缓存、消息、迁移、API、网关、worker、前端都能在 Aspire 里看到启动状态。开发期看拓扑,交付期按同一拓扑准备容器和环境变量,减少“本地能跑,部署缺依赖”的问题。

登录页现在也属于交付边界。它不是静态宣传页,而是管理中台的后台入口:工号密码登录、双语切换、生产预览和同步状态都在同一个前端运行时里。部署时如果 Web 容器没有真正 serve 构建后的 dist,后台人员就无法进入这些管理能力。
Gateway 收口入口
Gateway 的职责是统一入口和路径分流。IIoT.Gateway 通过 YARP 反向代理把请求转到 HttpApi。业务路径包括 /api/v1/human/*、/api/v1/edge/*、/api/v1/bootstrap/* 等。
这几类路径对应不同入口:
human:后台人员使用的管理中台接口。edge:上位机设备侧上传和查询接口。bootstrap:边缘设备启动寻址和设备身份确认入口。
Gateway 把这些路径先收口,再转给后端业务服务。认证、代理、路径管理和外部访问口径集中处理。业务规则仍然放在应用服务和领域层,Gateway 不承载设备、配方、产能等业务判断。
DataWorker 承接后台节奏
DataWorker 的存在和产线数据上传有关。
现场上位机上传数据时,入口链路要短。HttpApi 负责接收、校验、幂等和事件投递。设备日志、小时产能、过站数据这些归档动作,通过 RabbitMQ 和 DataWorker consumer 承接。代码里能看到 DeviceLogConsumer、HourlyCapacityConsumer、PassStationConsumer<TEvent>,也能看到 DataWorker 注册 MassTransit 和对应队列。
这种拆分避免把后台慢任务压到上传入口上。现场上传链路需要稳定返回,后台处理需要能重试、能观察、能扩展。DataWorker 单独运行,正好承接这类工作。
部署模板也是系统边界
部署不是最后补一个脚本。管理中台能否交付,取决于部署模板是否把运行依赖讲清楚。
项目部署里要关注几个点:
- PostgreSQL 数据卷默认保留,不能因为更新服务误删历史数据。
- 迁移容器需要 JWT、种子管理员账号等初始化参数。
- Web 容器要实际 serve 构建后的
dist。 - Gateway 对外端口要和现场部署约定一致。
- 环境变量要在
.env和.env.example中保持一致。
这些内容属于交付边界的一部分。设备身份、配方版本、生产归档都在云端,一次错误部署可能直接影响现场数据可用性。AppHost 负责开发期组织,compose 模板负责交付期落地,两者共同构成管理中台的运行边界。
开发期用 Aspire 看清服务关系,部署期用容器模板固定运行依赖。管理中台不是一个单进程后台,而是一组围绕上位机管理、生产归档和设备身份运行的服务拓扑。
AppHost 解决的是本地开发和部署一致性
管理中台不是只有一个 API 服务。它依赖数据库、缓存、消息队列、迁移程序、前端、网关和后台 worker。AppHost 把这些资源放进同一个编排入口,本地开发时能看到每个资源的运行状态,部署时也能把服务边界带到容器结构里。
这个结构对后期收尾很有用。云端主体能力封存后,后续新增工序默认只做必要 DTO、Command、Validator、事件契约、持久化表、查询接口和前端展示字段。AppHost、Gateway、DataWorker、PostgreSQL/TimescaleDB、Redis、RabbitMQ 这些主链路不应该因为新增一个字段被重开。
Gateway 和 HttpApi 的分工
Gateway 是外部入口收口层,HttpApi 是业务接口承接层。/api/v1/human/*、/api/v1/edge/*、/api/v1/bootstrap/* 这类入口集中到 Gateway 后,外部访问路径更稳定。HttpApi 内部处理人员、设备、配方、bootstrap、上传和查询等业务能力。
这样拆的收益是部署和演进都更清楚。入口策略、转发、跨域和前端访问路径可以在 Gateway 侧收敛;业务规则、DTO、Command 和 Controller 保持在 HttpApi 内。后续如果只改生产数据接入,不需要改变所有外部访问口径。
容器部署要保留数据边界
容器部署不能只看进程能不能起来,还要看数据是否安全保留。PostgreSQL/TimescaleDB 保存管理中台的主数据和历史归档,Redis 和 RabbitMQ 承担缓存与消息,DataWorker 负责消费处理。部署更新时默认保留数据库卷,不应把清库当成普通修复手段。
当前部署基线还要求外部 gateway 端口保持 GATEWAY_HTTP_PORT=81,迁移服务必须拿到 JWT、种子管理员账号、密码和真实姓名等环境变量。这些不是细枝末节,而是管理中台能否稳定启动和初始化的交付条件。
为什么部署也属于架构设计
部署不是项目收尾时才补的脚本。管理中台的服务边界如果在部署里丢掉,本地开发时的结构就无法稳定交付。Gateway、HttpApi、DataWorker、MigrationWorkApp 和前端分别承担不同职责,容器部署需要保留这些边界,不能为了少几个进程把它们混回一个入口。
环境变量也属于交付口径。JWT 密钥、种子管理员、数据库连接、gateway 端口和前端运行方式都直接影响系统能不能启动、能不能登录、能不能接收上位机数据。部署模板里缺一个关键变量,不应该被解释成运行时小问题,而是交付缺口。
AppHost 和容器结构对齐后,后续新增业务接入就有稳定落点。本地能观察服务,部署能按同样边界运行,问题定位也能从具体资源入手,而不是在一个黑盒进程里猜。
浙公网安备 33010602011771号