IoT DC3 这个项目,最早是我做设备接入平台选型时挖到的。当时团队需要一个能快速跑起来的 Spring Cloud 物联网框架,既要能管设备,又要能收 MQTT 数据,还得有现成的存储链路。翻了好几个开源项目,DC3 给我的印象最直接:它不是一堆代码堆在一起的单体应用,而是正经的微服务划分,网关、认证、管理、数据、监控各司其职,中间件也是业界常用的一套。说白了,这就是一套能本地跑起来、能二次开发的 Spring Cloud 物联网脚手架。
我把它完整部署到本地的过程,说实话不算太轻松。中间件多、服务多、配置链路长,踩了不少坑。所以这篇文章我想原原本本把整套流程记录下来,从架构认知讲到环境准备,从源码编译讲到 Compose 编排,再把遇到过的典型问题整理成排查清单。适合刚入行想做 IoT 平台的 Java 工程师,也适合拿微服务做毕设、做内部项目的同学,还有手里有设备数据想快速验证接入方案的从业者。照着走完,你至少能得到一套能登录、能建产品、能收 MQTT 数据的 DC3 环境。
1. 先把 DC3 看明白:项目定位与部署价值
1.1 DC3 能干什么:核心能力拆解
从功能模块看,DC3 不是一个大而全的商业物联网平台,而是一个基础框架,核心能力可以总结成三块:设备接入与设备管理、数据采集与存储、平台基础能力。
设备接入层面,DC3 主推的是 MQTT 协议接入。你在平台上创建产品、创建设备,然后设备通过 MQTT 往指定 topic 上报数据,平台侧的 data 服务负责消费消息,解析后落库。整个过程跑通之后,你就能在自己的业务里做设备状态监控、数据转发、告警之类的事情。它还预留了驱动扩展的思路,不同协议可以在驱动层适配,这也是很多人在选型时看上它的原因。
数据存储层面,DC3 用了 MySQL、MongoDB、InfluxDB 三个数据库组合。MySQL 存平台元数据,比如产品模型、设备列表、租户信息;MongoDB 用来存设备上报的非结构化消息内容;InfluxDB 单独存时序数据,适合做指标趋势分析。Redis 在这里主要做缓存,RabbitMQ 承担服务间的消息解耦。这套技术选型不算花哨,但很务实,每个中间件定位清晰,对初学者来说反而更容易理解。
1.2 为什么要本地部署一套 DC3
很多人在网上看过 DC3 的演示截图,觉得功能也就那样。但演示和亲手跑起来完全是两回事。本地部署的价值至少有四点。
第一,理解微服务架构。DC3 的模块划分非常典型,gateway 做统一入口、auth 做认证、manager 管业务、data 管数据、monitor 做监控。你把这套服务全部启动起来,观察它们之间怎么注册、怎么调用、怎么通信,比看十篇架构文章都管用。当你在 Nacos 控制台上看到服务列表一个个出现的时候,对“服务注册与发现”这个概念基本就通了。
第二,为二次开发打基础。你要给 DC3 加驱动、改协议解析、对接自己的业务系统,光看代码是不行的,必须有本地能跑的环境,改完代码立刻验证。没有本地环境,所有改动都是空谈。
第三,验证部署可行性。工作中经常要帮团队评估一个框架能不能落地。本地部署一遍,端口、内存、依赖、启动顺序这些坑都会暴露出来,你心里就有底了。文章后面记录的踩坑内容,基本就是我当初真实趟过一遍的结果。
第四,学习中间件组合。DC3 依赖的中间件种类多,MySQL、Redis、MongoDB、InfluxDB、RabbitMQ、Nacos 全都有。平时你可能只接触其中一两个,部署 DC3 等于把这些中间件一次性全用起来,对整个技术栈的认知会完整很多。
2. 架构与依赖:部署之前必须知道的事
2.1 微服务骨架和模块职责
DC3 的项目仓库是典型的多模块 Maven 工程,顶层会有 dc3-common 这类公共模块,放通用的工具类、实体类、Feign 接口定义。业务相关的服务,我部署过的版本里核心有这么几个:
- dc3-register:注册中心相关封装,在 Docker 部署里对应的就是 Nacos 容器
- dc3-gateway:API 网关,基于 Spring Cloud Gateway,是前端和外部请求的统一入口
- dc3-auth:认证服务,负责用户登录、Token 颁发与校验
- dc3-manager:管理服务,产品管理、设备管理、租户管理等平台核心业务
- dc3-data:数据服务,消费设备上报消息,负责数据解析、存储和对外查询
- dc3-monitor:监控服务,基于 Spring Boot Admin,展示各服务的运行状态
你不需要记死每个服务的内部代码,但要理解一条链路:请求从客户端进来先到 gateway,由 gateway 鉴权并转发;要业务数据就去 manager;设备数据上报走 data 链路。服务之间通过 OpenFeign 做内部调用,注册中心统一协调。整体结构就是很标准的 Spring Cloud 微服务写法,如果你做过相关项目,看这套代码会非常亲切。
有一点要注意,dc3-register 这个模块在不同版本里的形态可能不一样,有的版本用独立的 Nacos 容器,有的版本会通过这个模块启动内嵌 Nacos。部署的时候以你拉到的仓库文档为准,不用在这上面花太多时间纠结,你只要知道注册中心是 Nacos 就够了。
2.2 中间件选型和数据流
DC3 依赖的中间件比较多,本地部署前最好先列一个清单,知道谁是干嘛的,否则后面启动报错你都不知道该查谁。
| 中间件 | 默认端口 | 在 DC3 中的角色 |
|---|---|---|
| MySQL | 3306 | 平台元数据,如产品、设备、租户、用户表 |
| Redis | 6379 | 缓存,部分会话信息与认证数据 |
| MongoDB | 27017 | 设备上报消息的原始存储 |
| InfluxDB | 8086 | 时序数据存储,适合指标趋势分析 |
| RabbitMQ | 5672、15672 | 服务间消息解耦,设备数据流转 |
| Nacos | 8848 | 服务注册与配置中心 |
数据流的逻辑大致是这样:设备通过 MQTT 上报消息,平台把原始消息写入 MongoDB,同时解析出需要的字段写入 InfluxDB;管理端和 API 层要查询设备状态、历史数据时,分别从 MySQL 拿元数据、从 InfluxDB 拿时序数据、从 MongoDB 拿原始记录。RabbitMQ 在这个过程中负责削峰解耦,避免上报高峰把业务服务冲垮。
在本地部署时,这些中间件跑不跑得起来、配置对不对,直接决定后面服务能不能正常启动。所以我的建议是:别急着把平台服务编排上去,先把中间件逐个跑起来,确认健康了再上平台服务。这个顺序特别重要,尤其是第一次部署,能帮你把问题范围缩小一大半。
3. 安装前的环境准备:JDK、Docker 与源码拉取
3.1 本地环境清单与版本选择
先说说我实际使用的环境。DC3 是基于 Java 8 和 Spring Boot 2.x 这一版技术栈做的,所以 JDK 必须用 1.8,不要为了追新去用 JDK 11 或 17,否则编译期就可能出现各种版本兼容问题。我一开始图省事装了 JDK 17,结果 Maven 编译直接报错,换回 JDK 8 后一路顺畅。Maven 建议 3.6 以上,Git 肯定要装。Docker 这块,Windows 和 macOS 用 Docker Desktop,Linux 直接装 Docker Engine,记得把 Docker Compose 插件配好。
前端项目 dc3-web 是 Vue 技术栈,如果你打算本地跑前端调试,需要 Node.js,建议装 14.x 或 16.x 的 LTS 版本。如果只想要一个能用的后台,可以把前端构建产物放到 Nginx 里,或者直接用 dev server 起一个开发环境,这个后面专门说。
还有一项是端口规划。DC3 全家桶涉及的端口至少包括 3306、6379、27017、8086、5672、15672、8848,再加上网关、各个服务和前端的端口。本地部署前先检查一遍端口占用情况,Windows 上可以用netstat -ano | findstr <端口>,Linux 上可以用ss -lntp | grep <端口>,有冲突的先处理,别等启动报错才回来找。
3.2 源码获取与仓库结构说明
DC3 的主仓库在 GitHub,项目地址是iot-dc3/dc3,拉取命令很常规:
git clone https://github.com/iot-dc3/dc3.git cd dc3前端仓库是独立的,叫iot-dc3/dc3-web,需要单独拉:
git clone https://github.com/iot-dc3/dc3-web.git拉下来之后先看仓库根目录的 README 和docker-compose.yml。版本不同,目录结构和脚本多少会有差异。我部署的时候发现仓库里既有完整的 Compose 编排,也有每个服务单独的 Dockerfile,甚至有些模块带直接构建脚本。多花十分钟读 README,比盲目执行一堆命令靠谱得多。
另外,国内拉取依赖容易慢,Maven 的settings.xml里建议配置国内镜像仓库,这个属于常规操作,关键字搜“Maven 阿里云镜像”就能找到配置方式。网络环境下我踩过几次依赖下载超时,配完镜像基本就稳了。
4. 从源码到可运行的镜像:编译与构建
4.1 Maven 多模块编译
DC3 是多模块工程,第一次编译建议在根目录直接执行:
mvn clean package -Dmaven.test.skip=true这里-Dmaven.test.skip=true很重要,它跳过测试编译和测试执行,既能省时间,也能避开部分测试用例需要外部中间件环境的问题。整个项目模块多,第一次编译下载依赖会花不少时间,耐心等,只要网络正常、JDK 版本对,一般都能过。
编译完成后,各个服务的可执行 jar 包会生成在各自模块的target目录。你可以选择直接用java -jar启动,比如:
java -jar dc3-manager/target/dc3-manager.jar但本地部署更推荐用 Docker,因为中间件多,Docker 能统一管理生命周期。不过有一点要注意,直接用 jar 启动和用 Docker 启动,配置文件的生效位置不一样。用 jar 启动时,Nacos 地址、数据库地址这些配置默认会去找localhost,而在容器里可能通过环境变量注入不同的地址。这个细节在外面部署的时候特别容易把人绕晕,第 5 节我会展开说。
4.2 构建 Docker 镜像的两种方式
DC3 的镜像构建,我实际中用过两条路。第一条是用仓库自带的 Dockerfile 手动构建。比如构建 manager 服务:
docker build -t dc3-manager:latest ./dc3-manager第二条是直接用 Compose 里配置的公共镜像。有些版本为了简化流程,会在docker-compose.yml里直接写镜像地址,这样你就不用本地构建了,docker compose pull直接拉镜像就能跑。
两条路各有利弊。手动构建能保证镜像和本地代码一致,适合你要改代码的场景;拉公共镜像最省事,但拿到的可能不是最新代码。我的建议是:第一步先用公共镜像把环境跑通,确认没有版本兼容问题后,再决定要不要本地构建镜像。这样能把环境的坑和代码的坑分开排查,效率高很多。
5. 使用 Docker Compose 搭建本地环境
5.1 基础中间件先启动
DC3 对中间件的依赖前面已经列过表了。正式跑平台服务之前,先把基础设施组件启动起来。如果你拉到的仓库里有单独的docker-compose-infra.yml,直接用:
docker compose -f docker-compose-infra.yml up -d如果没有拆分文件,就手动挑出 mysql、redis、mongodb、influxdb、rabbitmq、nacos 这些容器单独启动:
docker compose up -d mysql redis mongodb influxdb rabbitmq nacos启动之后别急着下一步,先确认每个容器都健康。用docker ps看状态,等 Nacos 的 8848 端口能访问控制台了再继续。MySQL 和 MongoDB 第一次初始化可能要花一点时间,尤其 Nacos 自己要连 MySQL,启动顺序上通常放在 MySQL 之后。
实操提示:第一次部署千万别把所有容器一把梭全部用
up -d拉起,先中间件后服务,能帮你省下大量排查时间。同时启动的话,经常是平台服务早就起来了,Nacos 还没就绪,然后服务注册失败,你还要回头倒日志找原因。
5.2 启动平台核心服务
基础设施就绪后,再启动平台服务。命令类似:
docker compose up -d dc3-auth dc3-manager dc3-data dc3-gateway dc3-monitor平台服务起来之后,建议用docker compose logs -f dc3-manager这样的命令盯着日志。健康的服务标准是:在 Nacos 控制台的服务列表里能看到对应服务,并且服务状态显示正常。
这个阶段最容易翻车的是服务之间互相调不通。常见原因有几个:容器内部网络问题,比如配置里localhost指到了容器自己身上;数据库或 Nacos 的地址写的是容器名,但 Compose 网络没连通;再就是服务启动顺序错乱,A 服务启动时调 B 服务的 Feign 接口,B 还没注册上。这些问题在第 7 节排查部分我会逐个说。
5.3 前端项目启动与访问入口
后端起来之后,要访问管理界面还得把前端项目跑起来。前端是独立的dc3-web仓库,我本地用 dev server 最省事:
cd dc3-web npm install npm run dev默认开发服务器一般跑在http://localhost:8080,它会通过代理把 API 请求转发到后端的网关地址。如果前端页面能打开,但接口全报 404 或者跨域,第一件事就是去查前端配置文件里的代理目标和后端的网关地址对不对。
还有一种方式是用 Nginx 部署前端构建产物,适合模拟生产环境。执行npm run build,把dist目录丢给 Nginx,再把/api之类的路径反向代理到网关端口。这种方式更接近上线状态,但本地调试还是 dev server 改起来快。
登录后台时,默认账号密码每个版本可能不一样。我看到过 admin / admin,也见过初始化 SQL 里写的其他值。最靠谱的办法是去仓库里搜初始化 SQL,比如dc3.sql,直接在里面查用户表的初始记录。第一次登录成功后,第一件事建议先改密码,虽然是本地环境,但养成习惯没坏处。
6. 部署成功后的验证与体验
6.1 服务健康检查
如果你按前面的步骤操作完,现在应该有一套完整的 DC3 在本地跑着。我的建议是先做一轮健康检查,别急着登后台。
- 执行
docker ps,确认所有容器都是 Up 状态,没有反复重启的 - 打开 Nacos 控制台
http://localhost:8848/nacos,看服务列表里有没有注册上所有平台服务 - 打开监控服务的 Spring Boot Admin 界面,看各个服务的内存、线程、健康状态
- 用 curl 或者浏览器直接访问网关的健康检查接口,确认网关本身正常
这几项里,Nacos 控制台的服务列表最直观。看到所有服务都亮着,说明注册中心这条链路没问题,剩下的就是业务功能验证了。
6.2 第一次登录和设备接入实战
登录后台后,建议按“产品、设备、数据上报、数据查询”的顺序走一遍。先创建一个产品,定义好产品模型;再在产品下注册一个测试设备,拿到设备标识;然后找一个 MQTT 客户端工具,比如 MQTTX,以设备身份往平台接入 topic 推送数据。
推送之后,去后台的数据管理页或者直接查 InfluxDB,看数据有没有落库。如果能看到数据,恭喜你,整套链路已经通了。这一步的体验比什么架构图都实在,你能亲眼看到一条设备消息从 MQTT 进来,到 MongoDB、InfluxDB 各存一份,再到前端页面展示出来。这个端到端跑通的感觉,能帮你把前面所有模块和中间件串成一张图。
实际测试时,我建议先用固定字段的 JSON 消息,别上来就搞复杂的自定义协议。先把链路调通,再去研究模型定义和解析规则,这样排查问题的时候能缩小范围,不会眉毛胡子一把抓。
7. 踩坑记录:本地部署常见问题排查
7.1 端口占用与调整
本地环境最常见的坑就是端口被占。Windows 上经常是 3306 被本机 MySQL 占了,8080 被其他 Web 服务占了。处理办法是在 Compose 文件里改宿主机映射端口,比如:
ports: - "3307:3306"但要注意,改端口不能只改 Compose。平台服务的配置里如果写死了数据库连接串,你也得同步改成新端口,否则容器里面连的还是 3306,宿主机上却没有 3306。这类配置串联问题,排查时要顺着连接关系一层层找,别改了一个地方就以为完事了。
7.2 内存不足导致容器反复退出
DC3 全家桶的容器数量不少,就算只跑基础功能,全部加起来对内存也有一定要求。我实测下来,至少要给 Docker 分配 6G 以上的内存才比较稳,8G 更从容。如果你发现容器起来又挂、挂完又起,或者服务日志里出现内存溢出相关字眼,基本上就是内存不够。Windows 的 Docker Desktop 可以在 Settings 的资源选项里调内存和 CPU,Linux 上注意检查一下 swap 空间。这个问题看着低级,实际翻车率非常高,尤其是 16G 内存的电脑,不开 Docker 还好,一开全家桶直接卡成 PPT。
7.3 Nacos 启动失败与服务注册超时
Nacos 本身依赖 MySQL 存储配置和数据,所以它的启动顺序必须在 MySQL 之后。如果 Nacos 一直启动失败,先去 Nacos 的日志里看有没有数据库连接报错,确认初始化脚本有没有执行。另外,平台服务注册超时也很常见。解决方案很简单:等 Nacos 完全就绪再启动服务,或者在 Compose 里给服务加depends_on和健康检查条件。但要注意,depends_on只是容器层面的依赖,不能完全保证 Nacos 内部初始化完成,所以看日志、看健康检查仍然是最稳妥的做法。
7.4 前端页面打开但接口报错
前端能打开但数据加载不出来,十有八九是代理配置问题。拿 Vue dev server 来说,vue.config.js里的代理目标必须指到网关的真实地址。我遇到过一种情况:前端的代理指向了localhost:8080,但那台机器上 8080 被别的服务占着,网关实际跑在 8081,结果页面一直在转圈。排查套路是:先在浏览器 F12 里看请求地址和返回状态,再顺着地址去查网关、查网关转发的目标服务,逐层定位。跨域问题同理,后端网关如果没开对应的跨域配置,前端接口一样会挂。
还有一个很隐蔽的坑:服务全部启动成功后,第一次登录没问题,过一会儿再操作就提示 Token 失效或者权限不足。这种情况通常和 Redis 有关,认证信息存在 Redis 里,如果 Redis 里的数据被清了,或者配置的 Redis 库序号和认证服务启动时初始化用的库不一致,就会出现这种时好时坏的诡异现象。遇到这类问题,我一般会先把 Redis 清干净,同时检查各服务配置里的 Redis db 序号是否一致。
为了便于快速定位,我把几个高频问题整理成了一张速查表:
| 现象 | 大概率原因 | 处理建议 |
|---|---|---|
| 容器起来又退出 | 内存不足 | 调大 Docker 内存,检查是否有 OOM 日志 |
| Nacos 启动失败 | 数据库未就绪或初始化脚本没执行 | 等 MySQL 健康后再启动 Nacos,查 Nacos 日志 |
| 服务注册不上 | 启动顺序或容器网络问题 | 等 Nacos 就绪,确认 Compose 网络连通 |
| 前端接口 404 | 代理目标或网关实际端口不一致 | 检查vue.config.js代理和网关监听端口 |
| 登录后 Token 反复失效 | Redis 库序号错乱或数据被清 | 核对各服务 Redis db 配置,清理后重启 |
最后说点实际的。整个 DC3 本地部署流程走完之后,我个人最大的收获不是能把平台跑起来,而是通过它把 Spring Cloud 微服务这套东西完整串了一遍。以前看概念,服务注册、网关转发、Feign 调用、配置中心,都是一个个孤立的知识点,亲手把 DC3 从源码部署起来之后,这些概念突然就串成了一条线。如果你也在学 Spring Cloud 或者想做物联网平台,强烈建议不要只看文档,找个开源项目,把它在自己电脑上跑起来,改几行代码,加一个设备,比什么教程都管用。
还有个实用小经验:部署这套环境如果中途失败了,别急着删了重来,先去看容器日志,绝大多数问题日志里都有明确线索。我踩过的坑里,大概有七成都是自己没看日志、凭感觉改配置,反而越改越乱。稳一点,一步步来,DC3 本地跑通并不难。