首页 > 编程语言 > 详细

性能监控之JMX监控docker中的java应用

时间:2021-06-29 23:20:13      阅读:25      评论:0      收藏:0      [点我收藏+]
今天在配置docker和JMX监控的时候,看到有一个细节和非容器环境中的JMX配置不太一样。所以在这里写一下,以备其他人查阅。

一般情况下,我们配置JMX只要写上下面这些参数就可以了。

以下是无密码监控时的JMX配置参数(有密码监控的配置和常规监控无异)。

  1. -Dcom.sun.management.jmxremote

  2. -Dcom.sun.management.jmxremote.port=9998

  3. -Djava.rmi.server.hostname=<serverip>

  4. -Dcom.sun.management.jmxremote.ssl=false

  5. -Dcom.sun.management.jmxremote.authenticate=false

但是在docker容器中这样配置的时候,会出现这个错误。?

技术分享图片

这里就要说明一下逻辑了。为什么会这样呢? 先看docker环境的网络结构。

容器使用默认的网络模型,就是bridge模式。在这种模式下是docker run时做的DNAT规则,实现数据转发的能力。所以我们看到的网络信息是这样的:

docker中的网卡信息:

  1. [root@f627e4cb0dbc /]# ifconfig

  2. eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> ?mtu 1500

  3. ? ? ? ?inet 172.18.0.3 ?netmask 255.255.0.0 ?broadcast 0.0.0.0

  4. ? ? ? ?inet6 fe80::42:acff:fe12:3 ?prefixlen 64 ?scopeid 0x20<link>

  5. ? ? ? ?ether 02:42:ac:12:00:03 ?txqueuelen 0 ?(Ethernet)

  6. ? ? ? ?RX packets 366 ?bytes 350743 (342.5 KiB)

  7. ? ? ? ?RX errors 0 ?dropped 0 ?overruns 0 ?frame 0

  8. ? ? ? ?TX packets 358 ?bytes 32370 (31.6 KiB)

  9. ? ? ? ?TX errors 0 ?dropped 0 overruns 0 ?carrier 0 ?collisions 0

docker中的路由信息:

  1. [root@a2a7679f8642 /]# netstat -r

  2. Kernel IP routing table

  3. Destination ? ? Gateway ? ? ? ? Genmask ? ? ? ? Flags ? MSS Window ?irtt Iface

  4. default ? ? ? ? gateway ? ? ? ? 0.0.0.0 ? ? ? ? UG ? ? ? ?0 0 ? ? ? ? ?0 eth0

  5. 172.18.0.0 ? ? ?0.0.0.0 ? ? ? ? 255.255.0.0 ? ? U ? ? ? ? 0 0 ? ? ? ? ?0 eth0

  6. [root@a2a7679f8642 /]#

宿主机上的对应网卡信息:

  1. docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> ?mtu 1500

  2. ? ? ? ?inet 172.18.0.1 ?netmask 255.255.0.0 ?broadcast 0.0.0.0

  3. ? ? ? ?ether 02:42:44:5a:12:8f ?txqueuelen 0 ?(Ethernet)

  4. ? ? ? ?RX packets 6691477 ?bytes 4981306199 (4.6 GiB)

  5. ? ? ? ?RX errors 0 ?dropped 0 ?overruns 0 ?frame 0

  6. ? ? ? ?TX packets 6751310 ?bytes 3508684363 (3.2 GiB)

  7. ? ? ? ?TX errors 0 ?dropped 0 overruns 0 ?carrier 0 ?collisions 0

宿主机上的路由信息:

  1. [root@7dgroup ~]# netstat -r

  2. Kernel IP routing table

  3. Destination ? ? Gateway ? ? ? ? Genmask ? ? ? ? Flags ? MSS Window ?irtt Iface

  4. default ? ? ? ? gateway ? ? ? ? 0.0.0.0 ? ? ? ? UG ? ? ? ?0 0 ? ? ? ? ?0 eth0

  5. link-local ? ? ?0.0.0.0 ? ? ? ? 255.255.0.0 ? ? U ? ? ? ? 0 0 ? ? ? ? ?0 eth0

  6. 172.17.208.0 ? ?0.0.0.0 ? ? ? ? 255.255.240.0 ? U ? ? ? ? 0 0 ? ? ? ? ?0 eth0

  7. 172.18.0.0 ? ? ?0.0.0.0 ? ? ? ? 255.255.0.0 ? ? U ? ? ? ? 0 0 ? ? ? ? ?0 docker0

  8. 192.168.16.0 ? ?0.0.0.0 ? ? ? ? 255.255.240.0 ? U ? ? ? ? 0 0 ? ? ? ? ?0 br-676bae33ff92

所以宿主机和容器是可以直接通信的,即便端口没有映射出来。如下所示:

  1. [root@7dgroup ~]# telnet 172.18.0.3 8080

  2. Trying 172.18.0.3...

  3. Connected to 172.18.0.3.

  4. Escape character is ‘^]‘.

另外,因为是桥接的,宿主机上还有类似veth0b5a080的虚拟网卡设备信息,如:

  1. veth0b5a080: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> ?mtu 1500

  2. ? ? ? ?ether 42:c3:45:be:88:1a ?txqueuelen 0 ?(Ethernet)

  3. ? ? ? ?RX packets 2715512 ?bytes 2462280742 (2.2 GiB)

  4. ? ? ? ?RX errors 0 ?dropped 0 ?overruns 0 ?frame 0

  5. ? ? ? ?TX packets 2380143 ?bytes 2437360499 (2.2 GiB)

  6. ? ? ? ?TX errors 0 ?dropped 0 overruns 0 ?carrier 0 ?collisions 0

这就是虚拟网卡对veth pair,docker容器里一个,宿主机一个。 在这种模式下,有几个容器,主机上就会有几个veth开头的虚拟网卡设备。

但是如果不是宿主机访问的话,肯定是不通的。如下图所示:?

技术分享图片

当我们用监控机 访问的时候,会是这样的结果。

  1. Zees-Air-2:~ Zee$ telnet <serverip> 8080

  2. Trying <serverip>...

  3. telnet: connect to address <serverip>: Connection refused

  4. telnet: Unable to connect to remote host

  5. Zees-Air-2:~ Zee$

因为8080是容器开的端口,并不是宿主机开的端口,其他机器是访问不了的。 这就是为什么要把端口映射出来给远程访问的原因,映射之后的端口,就会有NAT规则来保证数据包可达。

查看下NAT规则,就知道。

  1. [root@7dgroup ~]# iptables -t nat -vnL

  2. Chain PREROUTING (policy ACCEPT 171 packets, 9832 bytes)

  3. pkts bytes target ? ? prot opt in ? ? out ? ? source ? ? ? ? ? ? ? destination

  4. 553K ? 33M DOCKER ? ? all ?-- ?* ? ? ?* ? ? ? 0.0.0.0/0 ? ? ? ? ? ?0.0.0.0/0 ? ? ? ? ? ?ADDRTYPE match dst-type LOCAL

  5. Chain INPUT (policy ACCEPT 171 packets, 9832 bytes)

  6. pkts bytes target ? ? prot opt in ? ? out ? ? source ? ? ? ? ? ? ? destination

  7. Chain OUTPUT (policy ACCEPT 2586 packets, 156K bytes)

  8. pkts bytes target ? ? prot opt in ? ? out ? ? source ? ? ? ? ? ? ? destination

  9. 205K ? 12M DOCKER ? ? all ?-- ?* ? ? ?* ? ? ? 0.0.0.0/0 ? ? ? ? ? !60.205.104.0/22 ? ? ?ADDRTYPE match dst-type LOCAL

  10. ? ?0 ? ? 0 DOCKER ? ? all ?-- ?* ? ? ?* ? ? ? 0.0.0.0/0 ? ? ? ? ? !127.0.0.0/8 ? ? ? ? ?ADDRTYPE match dst-type LOCAL

  11. Chain POSTROUTING (policy ACCEPT 2602 packets, 157K bytes)

  12. pkts bytes target ? ? prot opt in ? ? out ? ? source ? ? ? ? ? ? ? destination

  13. 265K ? 16M MASQUERADE ?all ?-- ?* ? ? ?!docker0 ?172.18.0.0/16 ? ? ? ?0.0.0.0/0

  14. ? ?0 ? ? 0 MASQUERADE ?all ?-- ?* ? ? ?!br-676bae33ff92 ?192.168.16.0/20 ? ? ?0.0.0.0/0

  15. ? ?0 ? ? 0 MASQUERADE ?tcp ?-- ?* ? ? ?* ? ? ? 192.168.0.4 ? ? ? ? ?192.168.0.4 ? ? ? ? ?tcp dpt:7001

  16. ? ?0 ? ? 0 MASQUERADE ?tcp ?-- ?* ? ? ?* ? ? ? 192.168.0.4 ? ? ? ? ?192.168.0.4 ? ? ? ? ?tcp dpt:4001

  17. ? ?0 ? ? 0 MASQUERADE ?tcp ?-- ?* ? ? ?* ? ? ? 192.168.0.5 ? ? ? ? ?192.168.0.5 ? ? ? ? ?tcp dpt:2375

  18. ? ?0 ? ? 0 MASQUERADE ?tcp ?-- ?* ? ? ?* ? ? ? 192.168.0.8 ? ? ? ? ?192.168.0.8 ? ? ? ? ?tcp dpt:8080

  19. ? ?0 ? ? 0 MASQUERADE ?tcp ?-- ?* ? ? ?* ? ? ? 172.18.0.4 ? ? ? ? ? 172.18.0.4 ? ? ? ? ? tcp dpt:3306

  20. ? ?0 ? ? 0 MASQUERADE ?tcp ?-- ?* ? ? ?* ? ? ? 172.18.0.5 ? ? ? ? ? 172.18.0.5 ? ? ? ? ? tcp dpt:6379

  21. ? ?0 ? ? 0 MASQUERADE ?tcp ?-- ?* ? ? ?* ? ? ? 172.18.0.2 ? ? ? ? ? 172.18.0.2 ? ? ? ? ? tcp dpt:80

  22. ? ?0 ? ? 0 MASQUERADE ?tcp ?-- ?* ? ? ?* ? ? ? 172.18.0.6 ? ? ? ? ? 172.18.0.6 ? ? ? ? ? tcp dpt:9997

  23. ? ?0 ? ? 0 MASQUERADE ?tcp ?-- ?* ? ? ?* ? ? ? 172.18.0.6 ? ? ? ? ? 172.18.0.6 ? ? ? ? ? tcp dpt:9996

  24. ? ?0 ? ? 0 MASQUERADE ?tcp ?-- ?* ? ? ?* ? ? ? 172.18.0.6 ? ? ? ? ? 172.18.0.6 ? ? ? ? ? tcp dpt:8080

  25. ? ?0 ? ? 0 MASQUERADE ?tcp ?-- ?* ? ? ?* ? ? ? 172.18.0.3 ? ? ? ? ? 172.18.0.3 ? ? ? ? ? tcp dpt:9995

  26. ? ?0 ? ? 0 MASQUERADE ?tcp ?-- ?* ? ? ?* ? ? ? 172.18.0.3 ? ? ? ? ? 172.18.0.3 ? ? ? ? ? tcp dpt:8080

  27. Chain DOCKER (3 references)

  28. pkts bytes target ? ? prot opt in ? ? out ? ? source ? ? ? ? ? ? ? destination

  29. 159K 9544K RETURN ? ? all ?-- ?docker0 * ? ? ? 0.0.0.0/0 ? ? ? ? ? ?0.0.0.0/0

  30. ? ?0 ? ? 0 RETURN ? ? all ?-- ?br-676bae33ff92 * ? ? ? 0.0.0.0/0 ? ? ? ? ? ?0.0.0.0/0

  31. ? ?1 ? ?40 DNAT ? ? ? tcp ?-- ?!docker0 * ? ? ? 0.0.0.0/0 ? ? ? ? ? ?0.0.0.0/0 ? ? ? ? ? ?tcp dpt:3307 to:172.18.0.4:3306

  32. ? 28 ?1486 DNAT ? ? ? tcp ?-- ?!docker0 * ? ? ? 0.0.0.0/0 ? ? ? ? ? ?0.0.0.0/0 ? ? ? ? ? ?tcp dpt:6379 to:172.18.0.5:6379

  33. 2289 ?137K DNAT ? ? ? tcp ?-- ?!docker0 * ? ? ? 0.0.0.0/0 ? ? ? ? ? ?0.0.0.0/0 ? ? ? ? ? ?tcp dpt:91 to:172.18.0.2:80

  34. ? ?3 ? 192 DNAT ? ? ? tcp ?-- ?!docker0 * ? ? ? 0.0.0.0/0 ? ? ? ? ? ?0.0.0.0/0 ? ? ? ? ? ?tcp dpt:9997 to:172.18.0.6:9997

  35. ? ?0 ? ? 0 DNAT ? ? ? tcp ?-- ?!docker0 * ? ? ? 0.0.0.0/0 ? ? ? ? ? ?0.0.0.0/0 ? ? ? ? ? ?tcp dpt:9996 to:172.18.0.6:9996

  36. ? ?0 ? ? 0 DNAT ? ? ? tcp ?-- ?!docker0 * ? ? ? 0.0.0.0/0 ? ? ? ? ? ?0.0.0.0/0 ? ? ? ? ? ?tcp dpt:9002 to:172.18.0.6:8080

  37. ? 12 ? 768 DNAT ? ? ? tcp ?-- ?!docker0 * ? ? ? 0.0.0.0/0 ? ? ? ? ? ?0.0.0.0/0 ? ? ? ? ? ?tcp dpt:9995 to:172.18.0.3:9995

  38. ? ?4 ? 256 DNAT ? ? ? tcp ?-- ?!docker0 * ? ? ? 0.0.0.0/0 ? ? ? ? ? ?0.0.0.0/0 ? ? ? ? ? ?tcp dpt:9004 to:172.18.0.3:8080

  39. [root@7dgroup ~]#

我们看到了宿主机的91端口的数据会传给172.18.0.2的80端口。宿主机的3307会传给172.18.0.4的3306端口。

啰啰嗦嗦说到这里,那和JMX有啥关系。苦就苦在,JMX是这样的。?

技术分享图片

  1. 在注册时使用的是参数jmxremote.port,然后返回一个新的端口jmxremote.rmi.port。

  2. 在调用服务时使用是参数jmxremote.rmi.port。 前面提到了,因为docker在bridge模式下端口是要用-p显式指定的,不然没NAT规则,数据包不可达。所以在这种情况下,只能把jmxremote.rmi.port也暴露出去。所以必须显式指定。因为不指定的话,这个端口会随机开。随机开的端口又没NAT规则,所以是不通的了。 所以,这种情况只能指定jmxremote.rmi.port为固定值,并暴露出去。 配置如下:

  1. -Dcom.sun.management.jmxremote

  2. -Dcom.sun.management.jmxremote.port=9995

  3. -Djava.rmi.server.hostname=<serverip>

  4. -Dcom.sun.management.jmxremote.ssl=false

  5. -Dcom.sun.management.jmxremote.authenticate=false

  6. -Dcom.sun.management.jmxremote.rmi.port=9995

像上面的设置就是两个都是9997,这样是允许的,这种情况下注册和调用的端口就合并了。

再启动docker容器的时候,就需要这样了。

  1. docker run -d -p 9003:8080 -p 9995:9995 --name 7dgroup-tomcat5

  2. -e CATALINA_OPTS="-Dcom.sun.management.jmxremote \

  3. -Dcom.sun.management.jmxremote.port=9995 \

  4. -Djava.rmi.server.hostname=<serverip> \

  5. -Dcom.sun.management.jmxremote.ssl=false \

  6. -Dcom.sun.management.jmxremote.authenticate=false \

  7. -Dcom.sun.management.jmxremote.rmi.port=9995" c375edce8dfd

然后就可以连接上JMX的工具了。?

技术分享图片

技术分享图片

技术分享图片

在有防火墙和其他的设备的网络环境中,也有可能出同样的问题。明白了JMX的注册调用逻辑之后,就可以解决各种类似的问题了。

网络链路是做性能分析的人必须想明白的技术点,所以前面说了那么多内容。

这里对于JMX工具的选择啰嗦两句。有人喜欢花哨的,有人喜欢简单的,有人喜欢黑窗口的。我觉得工具选择的时候,要看适用情况,在性能分析的时候,一定要选择合适的工具,而不是选择体现技术高超的工具。

最后留个作业:

  1. 如果docker run中如果指定-p 19995:9995,也就是换个端口暴露出去,其他配置都不变。JMX工具还能连得上吗?

  2. 如果jmxremote.rmi.port和jmxremote.port不合并,并且同时把两个端口都暴露出去,其他配置都不变。JMX工具还能连得上吗?

有兴趣的可以自己尝试下哦。

?

性能监控之JMX监控docker中的java应用

原文:https://blog.51cto.com/u_15181572/2955002

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!