
评估一个 IoT 平台的云原生程度,关键看三件事:服务怎么切、服务之间怎么说话、一个请求从进来到落地经过几层。这篇以 DC3 为样本拆一遍。
一条数据的完整旅程

DC3 的运行时链路是清晰的六层:
① 客户端层:Vue 3 + TypeScript 的 Web 前端,以及独立的 TypeScript CLI(dc3-cli)------后者不只是运维工具,也是给智能体和脚本用的命令行客户端。
② 网关层:Spring Cloud Gateway 作为唯一入口,静态路由 + 环境变量灵活配置。所有 REST 流量从这里过,认证、限流、MCP 端点也挂在这一层。客户端永远不需要知道后面有几个服务。
③ 中心服务层:四个按职责拆分的微服务------
- dc3-center-manager:设备、驱动、点位、模板、用户与权限,平台的管理面;
- dc3-center-data:位值数据的接收、批处理与读取,平台的数据面;
- dc3-center-auth:认证授权,token 签发与校验;
- dc3-center-agentic:AI Agentic Center,大模型接入与工具编排(也有把多服务合并部署的 center-single 形态,给小规模场景省资源)。
④ 消息总线层:驱动采集到的数据不直写数据库,而是发到消息总线(默认 RabbitMQ,可换 Kafka、Pulsar、MQTT、ActiveMQ、RocketMQ,第 04 篇专门讲)。削峰、解耦、驱动与数据中心互不拖累,全靠这一层。
⑤ 驱动层:36 个驱动作为独立微服务运行,各自连接各自的设备,采集频率与协议语义自持。
⑥ 设备层:现场的真实世界。
服务之间用 gRPC + Protobuf 通信------二进制序列化在高频的设备元数据查询场景比 JSON 更省,接口契约由 proto 文件管理,这也是"API 优先"能落地的基建。
边界:Facade 与三层模型

微服务架构的常见退化原因不是性能,而是边界失守:跨服务直连、数据库字段直接透传前端,最终导致模块难以变更。DC3 以两条硬性规则约束:
第一,跨服务调用必须走 Facade 接口。 业务代码不绑定传输细节------调用方依赖的是 Facade 接口,实现可以是进程内直调(小规模部署),也可以是 gRPC 远程调用(微服务部署),切换不惊动业务代码。
第二,数据模型三层分离:DO / BO / VO。 DO 对应数据库行结构,BO 承载业务语义(用领域枚举而不是裸的 0/1 标志位),VO 是 API 的请求响应形状。三者之间用 MapStruct 做映射。这带来了明确的收益:数据库编码位不会泄漏到前端;出现问题时可先检查单层映射,而非全链路排查。
加上全链路的租户隔离(每个查询带租户范围,缓存键带租户上下文),这套架构的取向很明确:以适当的编码成本换取长期可维护性。
实事求是的边界
- 无状态设计支持水平扩展,但"能扩"不等于"随便扩"------消息总线与 PostgreSQL 才是规模化时的真正瓶颈,扩容前先看这两层;
- center-single 单体形态是给资源受限场景的选项,不是所有场景都值得跑全量微服务;
- 完整规格以 docs.dc3.site 的 Architecture 章节为准。
仓库 :GitHub
pnoker/iot-dc3· Giteepnoker/iot-dc3(GVP)文档:docs.dc3.site(Architecture / Modules and Dependencies)· book.dc3.site · demo.dc3.site