Skip to content

从源码本地开发

这页带你把 IoT DC3 从源码跑起来:先用 Compose 起好 PostgreSQL 与 RabbitMQ,再用一组本地环境变量把 Java 进程指向本机端口,构建、启动、跑测试。读完你能在自己的机器上跑通整套中心服务,并理解为什么启动有先后、为什么本地进程不能直接吃根 .env

你在这里:想从源码开发或调试。只想点一遍最短闭环,请看 第一个设备:端到端;想理解服务怎么拼起来,请看 系统架构总览

先决条件

本地开发是"半容器"模式:基础设施(数据库、消息中间件)跑在容器里,中心服务以本地 Java 进程运行,方便断点调试与热重启。所以你需要一套 JDK/构建工具,外加一个容器运行时。

  • JDK 21 —— 平台强制 Java 21,低版本编译会直接失败。
  • Maven 3.9+ —— 仓库内置 .mvn/settings.xml 与并行构建配置;多模块打包用它。
  • pnpm —— 前端 iot-dc3-webdc3-cli 都用 pnpm(不要用 npm/yarn)。仅做后端开发可跳过。
  • Podman —— 本仓库容器操作一律用 podmanmake 默认 podman compose)。

为什么是这五步

本地起栈的最短闭环是五步,每一步都有明确产物,下一步依赖上一步的产物:先有基础设施(容器),才能加载指向它们的环境变量;先构建出 jar,才能启动开发栈;服务起来后才谈得上跑测试。

下面逐步展开,每步都给出"做什么"和"怎么验证"。

第一步:起基础设施

make up-db 用 Compose 拉起 db 栈——PostgreSQL 与 RabbitMQ。PostgreSQL 首次启动会按文件名顺序执行 initdb 脚本(扩展、common、auth、data、manager、history、agentic),把租户、用户、菜单、元数据表全部建好,所以第一次起会比后续慢。

bash
make up-db
bash
make up-db-cn

容器对宿主发布的端口是固定的:PostgreSQL localhost:35432、RabbitMQ AMQP localhost:35672(容器内部仍是 5432 / 5672)。验证:

bash
podman ps                          # 应看到 dc3-postgres、dc3-rabbitmq 在 running
podman exec dc3-postgres psql -U dc3 -d dc3 -c '\dt dc3_auth.*'   # 能列出 auth 表即就绪

可选可观测栈

需要 EMQX、ELK、Prometheus、Grafana 时,再执行 make up-optional。本地核心开发用不到,建议等中心服务稳定后再起,避免一次性拉起过多容器。

第二步:加载本地环境变量

bash
source dc3/env/dev.env.sh

这一步把数据库、RabbitMQ、MQTT、gRPC 目标主机等开发默认值导出到当前 shell。其中关键的是把 POSTGRES_HOST=localhostPOSTGRES_PORT=35432RABBITMQ_HOST=localhostRABBITMQ_PORT=35672、以及 CENTER_AUTH_HOST/MANAGER_HOST/DATA_HOST/AGENTIC_HOST=localhost 指向本机,让本地 Java 进程能连上第一步发布出来的容器端口。

.env 只给 Docker Compose 插值,不会注入本地 Java 进程

根目录 .env 是 Compose 专用的——它只在 docker compose 解析时做变量插值(镜像仓库、镜像 tag、发布端口),不会自动注入到你本地起的 Java 进程。本地从源码跑,必须 source dc3/env/dev.env.sh;否则服务会沿用容器内 DNS 名(如 dc3-postgres:5432),在本机根本解析不到,连接直接失败。

在 JetBrains IDEA 里运行时,用 EnvFile 插件加载不含 exportdc3/env/dev.env,或把其键值粘进运行配置的环境变量。

验证:echo $POSTGRES_PORT 应回显 35432

第三步:构建

bash
make package                       # 等价于 mvn -s .mvn/settings.xml clean package

仓库已配好并行构建、强制 JDK 21/Maven 3.9+、Spring Java Format 校验。构建产物是各服务模块的可执行 jar(如 dc3-gateway/target/dc3-gateway.jar)。这一步只验证编译与打包,不依赖第一步的容器。

快速编译检查

只想确认改动能编译、不想整包,用 mvn -s .mvn/settings.xml -q -DskipTests compile,比全量 package 快很多。

第四步:起开发栈

构建出 jar 后,用 dev 栈把中心服务跑起来。make up STACK=dev(或简写 make up-dev)按依赖顺序启动 Gateway、Auth、Manager、Data、Agentic 与驱动。

bash
make up-dev
bash
make up-dev-cn

为什么有先后顺序?因为服务之间有依赖:

  • Auth 中心要先就绪——它持有租户、用户、RBAC 与令牌签发逻辑,其它服务和网关的鉴权都依赖它。
  • Gateway 是唯一对外 HTTP 入口(8000),它聚合 Auth/Manager/Data/Agentic 的路由、抽取鉴权头、注入 principal 上下文。它要在后端中心服务可达之后才能正确转发,所以排在依赖项之后。
完整启动顺序与端口

分布式默认走 gRPC(DC3_FACADE_MODE=grpc,dev.env 已设)。各服务端口:

服务HTTPgRPC
Gateway / dc3-gateway(唯一对外入口)8000
鉴权中心 / dc3-center-auth83009300
管理中心 / dc3-center-manager84009400
数据中心 / dc3-center-data85009500
智能中心 / dc3-center-agentic8600

只有 Gateway(用户入口)与 listening-virtual 的 TCP 6270 / UDP 6271(设备入口)对宿主映射,其余后端端口都是内部端口。

验证:栈起来后,对网关跑一次登录黄金路径。登录分两步——先取盐,再用盐哈希后的密码换 12 小时有效的 access token:

bash
# 1) 取盐(公开端点,5 分钟有效)
curl -s -X POST http://localhost:8000/api/v3/auth/token/salt \
  -H 'Content-Type: application/json' \
  -d '{"tenant":"default","name":"dc3"}'      # 返回字符串 salt(示例值)

# 2) 用 salt 哈希密码后换 token(公开端点,access token 12 小时有效)
curl -s -X POST http://localhost:8000/api/v3/auth/token/generate \
  -H 'Content-Type: application/json' \
  -d '{"tenant":"default","name":"dc3","salt":"<上一步的 salt>","password":"<salt 哈希后的密码>"}'

拿到 token 后,受保护端点都通过网关访问,并带上三个鉴权头 X-Auth-TenantX-Auth-LoginX-Auth-Token。完整的"建驱动 → 建模板 → 建设备 → 读写位号"闭环见 第一个设备:端到端

第五步:跑测试

bash
make test                          # 单元测试套件

需要更高层验证时:make test-it 跑集成测试(需容器运行时供 Testcontainers),make test-e2e 跑后端 E2E。日常开发改完一处,先 make test 兜住单元回归即可。

常见坑

  • source dev.env.sh 就起服务——最常见。本地 Java 进程拿不到 localhost:35432 / 35672,会去连容器内 DNS 名而连不上。每开一个新 shell 都要重新 source(变量只在当前 shell 生效)。
  • podman 没起——make up-db 报连不上容器运行时,先确认 podman 守护进程/machine 已启动(macOS 上需 podman machine start),再用 podman ps 确认。
  • 端口被占——35432 / 35672 / 8000 等被其它进程占用时启动失败。释放占用进程,或在根 .env 中覆盖 Compose 发布端口(仅影响容器侧),本地进程端口用服务级环境变量覆盖。
  • 首次起库很慢或表不全——PostgreSQL 只在空卷首启时跑 initdb。若中途中断导致表不全,需重置卷重来:make reset STACK=db(需 CONFIRM_RESET_VOLUMES=true,会删数据,谨慎)。

生产密钥必须替换

dev.env.sh 里的 DC3_SECURITY_KEYAUTH_HMAC_SECRET 是开发默认值。在 pre/pro 环境,若 AUTH_HMAC_SECRET 为空或仍等于默认值 io.github.pnoker.dc3,Gateway 会 fail-fast 拒绝启动。本地开发无妨,上线前务必换成环境专属随机值。

延伸阅读

Released under the AGPL-3.0 License · 基于 AGPL-3.0 协议发布