扩展 EdgeX Foundry 混合开发环境
构建混合开发环境的原因
在上文中,我们介绍了 EdgeX Foundry 的背景和概况;在本文中,我们会介绍实现更高效率混合开发环境的一种方法。
EdgeX Foundry 的核心工程数目超过 11 个,这还不包括每个工程对应的 client 和 domain 等依赖工程。而绝大多数情况下,我们实际要开发是其北侧端的 export 服务和南侧端的 device 服务。如果把 EdgeX Foundry 全部代码放入本地的 Eclipse IDE 中,不仅配置复杂,而且对于资源有限的笔记本来说,启动 EdgeX Foundry 全部核心工程,所产生的卡顿现象将影响开发效率。
在 EdgeX Foundry 的官方文档中有提示建议采用混合开发模式:一部分核心工程运行在其他宿主机上,将开发所针对的单个工程运行在 Eclipse 中。不过如果用这种方法,需要在项目工程中更改几十处的 IP 地址,对于 IP 经常变化的环境中开发来说非常不方便。
Edgex Foundry 官方混合开发环境文档参考:
https://wiki.edgexfoundry.org/display/FA/Get+EdgeX+Foundry±+Developers
这里,我们介绍一种扩展的 EdgeX Foundry 混合开发环境,它是基于 Docker Swarm、 Eclipse 的远程调试、devtools 插件来实现的:
- Docker Swarm 用于集群部署,其内置的跨主机网络可以连接两个不同宿主机上的container。
- Eclipse 的远程调试,依赖 Spring Boot 的 devtools 热部署插件,该插件可以在修改代码的时候自动重新编译启动 Docker 容器中 Spring app 应用工程,所以项目不一定非要真是的跑在 Eclipse 中也能调试编写代码。
这种以 Docker container 和 Eclipse 远程调试的方式,不仅仅是为了扩展 EdgeX Foundry 开发环境。在任何以 jar 包启动并运行到 Docker 内的开发环境来说,这种方式可以解决如下问题:
- Jar 包运行的 Java 程序读取本地文件的方式与 War 包方式不同,更与 Eclipse 中开发时不同,经常会有在 Eclipse 中写好的代码放到 Docker 中后,运行报错问题。
- 更好地实时监控运行在 Docker 环境中的状态,有助于提前发现问题。
创建 Docker Swarm 的跨主机网络步骤
1. 下载操作系统对应版本的 docker-ce
ce指的是社区版本,社区版本已经足够使用,按官网安装即可。
2. 初始化 docker swarm
(1) 在 EdgeX Foundry 的宿主机上,执行如下命令:
docker swarm init
==>拷贝输出中的如下代码:
docker swarm join -token
SWMTKN-3e2t75c5a9zgl4i4hg7e871xq03s2nuf6rt2c716r8aad36nl34bllsvqym8i1
10.211.55.7:2377
(2) 在自己本机上执行上一步骤拷贝的代码到自己的 command 控制台中执行即可
成功后输出如下==>
This node joined a swarm as a worker.
这里表示你的主机已经成为 EdgeX Foundry 运行的宿主机的一个集群节点 node, 并且是 worker 模式。
work 模式 ==> 从机不能执行 docker node 的命令
manager 模式 ==> 从机作为主节点的一个备份节点,防止主节点宕机
在 Edgex Foundry 核心工程运行的宿主机上执行 docker node ls 可以查看有两个节点:一个是 Leader ,另一个没有状态的是 worker。
如果想把 work 提升为 manager 只需在 EdgeX Foudry 的宿主机上执行命令:docker node promote nodeID ==> 即可把 worker 从机提升为 manager。
3. 创建跨主机网络 multi-host network
(1) 在 EdgeX Foundry 核心工程运行的宿主机上执行如下命令:
docker network create --driver overlay --attachable test-overlay-network
==> 其中 --attachable 参数必须,否则容器无法连接,只能 service 模式连接
service 模式用于 Docker Swarm 分布式集群,且内置负载均衡,这里不深入讨论。
(2) EdgeX Foundry 宿主机上的执行如下命令加入跨主机网络:
docker network connect container_name test-overlay-network
注意:必须手动将每一个 EdgeX Foundry 的核心工程都加入到跨主机网络中,这不影响 EdgeX Foundry 已有的 docker 网络。
(3) 在 EdgeX Foundry 宿主机上继续执行如下命令验证创建跨主机网络创建成功:
docker network ls ==> 输出的结果中会有很多网络名,其中大部分是 Edgex Foundry 的,可以看到名字为 test-overlay-network 的网络名字已经存在。
注意:只有节点是 manager 的才能看到这个网络名字,如果你的 Eclipse 运行的宿主机是 worker 节点模式,执行这个命令是看不到 test-overlay-network ,但是这不影响你创建的容器去连接,建议将 docker worker 模式提升为 manager 模式。
4. 拉取 edgex git 上的 mqtt-service 工程到本地的 Eclipse 中
(1) 在 pom.xml 中添加 dev-tool 的依赖后,并添加如下设置:
(2) 在 application.properties 中配置如下设置:
spring.devtools.remote.secret=yoursecret ==>这个秘钥用于 Eclipse 远程调试
5. Eclipse 设置远程 debug 模式
(1) 配置远程 run 模式:
In Eclipse:
-Run->Run Configurations -> Java Application -> New
-选择 org.springframework.boot.devtools.RemoteSpringApplication as the main class
-选择 spring-dev-remote as the project ==>spring-dev-remote 是你的工程,必须在你的 Eclipse 中和 Docker 中有一个一样的工程。
-program arguments 选项卡设置 http://localhost:49982
==>ip 和端口号是运行 docker 的主机和 app 暴露的端口号
(2) 配置远程 debug 模式:
In Eclipse:
-Run选项卡->Debug configurations -> Remote Java Application -> New
-选择spring-dev-remote as the project ==>spring-dev-remote 是你的工程
-设置 connection properties 为 localhost and port 8000
6. 创建 mqtt-service 本机容器并和 edgex foundry 宿主机上的容器互联
(1) 在本地的宿主机的 Eclipse 中重新构建 mqtt-service 服务的 jar 包
(2) 在 mqtt-service 工程中的 Dockerfile 文件中 ENTRYPOINT 位置替换如下代码:
java -Xdebug
-Xrunjdwp:server=y,transport=dt_socket,suspend=n,address=8000
-jar mqtt-service.jar
==>address 必须设置,有的分享教程不设置 address,
包括官网也没特别指定,导致无法连接到远程主机。
(3) Eclipse 的宿主机上重新创构建镜像并创建 mqtt-service 容器:
使用修改后的 Dockerfile 重新构建 docker image。
基于新的 mqtt-service 镜像创建并启动容器:
docker create
-p 49982:49982
–network test-overlay-network ==>连接到跨主机网络
–hostname mqtt-service ==> 必须指定主机名且和容器名一样,与 consul 有关
–name mqtt-service ==>容器名
mqtt-service-image ==>重新构建的 mqtt-service 镜像名
7. 验证
在 run 模式下:在 Eclipse 中修改 mqtt-service 的代码,本地主机的 Eclipse 控制台中
输出 Springboot Banner 带有 remote 字样的标志,
并提示连接成功,此时在 Eclipse 修改代码,即可动态添加到本宿主机下的 container 中的工程中。
实际开发过程中,只需使用 debug 模式即可。
8. 替换 mqtt-service 中默认的 mqtt broker
(1) 使用 eclipse 开源的 mosquitto 作为本地的 broker。
(2) docker 中的镜像 mosquito broker 可以直接拉取 eclipse 官网打好的开源镜像
docker pull eclipse-mosquitto
docker run -it -d
–network test-overlay-network ==>加入跨主机网络,broker 可以在任何宿主机上
-p 1883:1883
-p 9001:9001
–name mosquitto-broker
eclipse-mosquitto
(3) mqtt-service 的 application.properties 文件中配置
9. mosquitto-clients 官方没有,但是调试时需要,所以需要自己构建
Dockerfile 构建文件如下:
构建镜像命令:
doker build . -t test-mosquitto-clients ==>-t 参数表示镜像名
最后一行的 ENTRYPOINT 可以不需要。
因为 mosquitto-clients 有 mosquitto_pub 发布和 mosquitto_sub 订阅两个命令,而且还要传入不同的订阅主题参数等,如果构建死了,那么不同的情景就需要不同的image,比较繁琐。所以去掉最后一行在创建 contianer 的时候传入,可基于一个mosquitto-clients 镜像同时创建发布和订阅主题多个业务级别的容器。
一个简单的创建容器命令如下:
docker create
–network test-overlay-network ==> 这是加入跨主机网络
–name test-mosq_sub ==>这是 container name
test-mosquitto-clients ==>这是 image
/usr/bin/mosquitto_sub ==>启动 container 的时候执行命令
-h mosquitto-broker ==>启动参数 args1 ,表示 broker 的主机名,这里是跨主机网络中域名
-t CommandTopic ==>启动参数 args2,表示订阅的主题