测试覆盖率 如何使用 jacoco 统计多个 docker 容器服务的测试覆盖率

luckyhey · 2020年12月10日 · 最后由 jsguo 回复于 2022年10月28日 · 6877 次阅读

某系统使用微服务架构,总共有 40 多个服务,都是使用 java 编写,docker 容器运行。如果要用 jacoco 统计这 40 多个服务的测试覆盖率,是不是要给每一个 docker 容器分配一个端口号?
像下面这样:hello 容器使用 6305 端口,world 容器使用 6306 端口.....
hello 容器 dockerfile 的部分内容
ENTRYPOINT ["java", "-javaagent:/tmp/jacocoagent.jar=includes=com.hello.,output=tcpserver,port=6305,address=", "-server", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app/hello.jar", "--server-port=8037"]
world 容器 dockerfile 的部分内容
ENTRYPOINT ["java", "-javaagent:/tmp/jacocoagent.jar=includes=com.world*,output=tcpserver,port=6306,address=*", "-server", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app/world.jar", "--server-port=8037"]
谢谢~~

共收到 12 条回复 时间 点赞

jacoco 的服务队的服务,准确的来说是针对每个服务都要开一个新的端口。我之前公司做的都是每个服务开一个端口来着。不知道这样的做法有没有改进的

不用啊,你采集覆盖率部分的服务也部署到 docker 同一个网络里面,就可以按主机名或者 ip 来区分各个服务了。

实际只有获取 ec 文件这个步骤需要访问这个端口,后续的生成报告啥的都是基于 ec 文件了。

陈恒捷 回复

我现在 30 多个 docker 容器放在同一台服务器 A 上,另外 10 个多容器放在服务器 B 上。是不是监控这 30 多个 docker 容器的端口号不能相同?A 上的 docker 容器 1 用端口 6305,A 上的 docker 容器 2 要用端口 6306?B 服务器上的 docker 容器 3 可以用 6305?

luckyhey 回复

端口是附属在 ip 下面的,基本对应关系是 ip=主机(不是物理上的,是逻辑上的,比如 docker 内部网络下,每个容器都有自己的 ip,但在 docker 网络外部,整个 docker 主机只有一个 ip),端口=应用

之所以不同应用要换端口,原因是一个 ip 下面一个端口只能绑定给一个应用监听,你多个应用绑定时,第二个开始就会绑定失败。

你在 docker 网络外部访问里面的容器,所有容器用的都是 docker 主机的 ip,自然必须要每个容器都用不同的端口。
当你在 docker 网络内部访问里面的容器(比如起一个采集服务的容器,访问其他容器),每个容器用的是 docker 内部网络分配的 ip,一个容器一个 ip,自然就不用错开端口了。
你例子写的也是一样,A 和 B 服务器只要是用不同的 ip ,就可以用同样的端口而不冲突,A 上面多个容器,每个就得错开端口。

楼主现在面对的问题,我正在干。
类似恒捷说的那样,一个容器你就把它当做一个独立的服务器来操作就可以。
我这边服务大概有 200 个左右,每个服务至少两个容器节点。 直接通过一个 k8s 的 master 节点,远程操作所有 container 就可以

ghost 回复

直接通过一个 k8s 的 master 节点,远程操作所有 container 就可以==========这个怎么理解?你的 400 个容器都是部署在 k8s 上面吗?

luckyhey 回复

是的,通过下面这个命令就可以直接在容器内操作,通过 jacoco 的命令行来收集 exec

kubectl exec -it <podName> -c <containerName> -n <namespace> -- shell comand
陈恒捷 回复

恒捷,你好。我正文中使用的是 On-The-Fly 插桩还是 Offine 插桩呢?我没有修改过开发人员的 pom.xml 文件,只是修改了他们的 dockerfile 文件。最近了解到可以在工程的 pom.xml 中引入 jacoco、jacoco-maven 的依赖,是不是修改 pom.xml 文件的这种方式更通用?谢谢!

luckyhey 回复

你这个是通过加 java agent 来弄的,属于 On the fly 。至于引入这个依赖,我理解是主要给单测覆盖率采集用的吧?没怎么玩过 java 服务的 offline 插桩(因为 On the fly 很香,没有什么改用 offline 的理由),不大清楚。

也补充说明下,一切覆盖率工具,原理上都得给原版代码加额外代码。加的这个代码主要是一个标记,让给某个指令/某一行代码的运行前后,改变这个标记(比如默认标记是 0,有跑过就变成 1),标识这一个指令/代码行执行了。
只是由于 java 这门语言支持运行时字节码增强技术,也提供了 java agent 这样的不用改源码就能改字节码的玩法,所以才出现了这种特别的看起来 “无侵入” 的加代码姿势。所以官方把这种方式比较形象地称为 on the fly(直译是飞行中,你可以理解为运行中插桩)。

但要注意,因为 java agent 本质上还是在运行时改了字节码的,所以原理上是完全可以改变代码逻辑的(比如 jvm-sandbox 官方例子里的,不改源码直接改变某个函数的行为来修 bug ),接入多个 java agent 也有可能产生相互影响出 bug ,所以不要觉得这个方式真的 “不侵入、无风险” 哈。

@ 陈恒捷 您好,搭车请教下,我在云主机上的服务 jacoco 可以正常采集数据生成报告,但是 k8s 容器中的生成的报告数据就是 0,exec 中也看不出执行过的接口相关的信息,jacoco 应用到 k8s 有要特别注意的地方吗?谢谢

ghost 回复

我现在已经在容器中生成 exec 文件,如果要生成 html 报告,还是要跟编译主机进行交互,请问这部分怎么解决的

moye 回复

你好 ,你的这个问题,我这边也遇到了, 请问你那边解决了吗?

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册