当前位置 : 主页 > 操作系统 > centos >

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

来源:互联网 收集:自由互联 发布时间:2022-06-20
今天在配置docker和JMX监控的时候,看到有一个细节和非容器环境中的JMX配置不太一样。所以在这里写一下,以备其他人查阅。 一般情况下,我们配置JMX只要写上下面这些参数就可以了。
今天在配置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容器中这样配置的时候,会出现这个错误。 

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

这里就要说明一下逻辑了。为什么会这样呢? 先看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开头的虚拟网卡设备。

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

性能监控之JMX监控docker中的java应用_显式_02

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

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.

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

7. pkts bytes target prot opt in out source destination

8.

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

10. pkts bytes target prot opt in out source destination

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

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

13.

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

15. pkts bytes target prot opt in out source destination

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

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

18. 0 0 MASQUERADE tcp -- * * 192.168.0.4 192.168.0.4 tcp dpt:7001

19. 0 0 MASQUERADE tcp -- * * 192.168.0.4 192.168.0.4 tcp dpt:4001

20. 0 0 MASQUERADE tcp -- * * 192.168.0.5 192.168.0.5 tcp dpt:2375

21. 0 0 MASQUERADE tcp -- * * 192.168.0.8 192.168.0.8 tcp dpt:8080

22. 0 0 MASQUERADE tcp -- * * 172.18.0.4 172.18.0.4 tcp dpt:3306

23. 0 0 MASQUERADE tcp -- * * 172.18.0.5 172.18.0.5 tcp dpt:6379

24. 0 0 MASQUERADE tcp -- * * 172.18.0.2 172.18.0.2 tcp dpt:80

25. 0 0 MASQUERADE tcp -- * * 172.18.0.6 172.18.0.6 tcp dpt:9997

26. 0 0 MASQUERADE tcp -- * * 172.18.0.6 172.18.0.6 tcp dpt:9996

27. 0 0 MASQUERADE tcp -- * * 172.18.0.6 172.18.0.6 tcp dpt:8080

28. 0 0 MASQUERADE tcp -- * * 172.18.0.3 172.18.0.3 tcp dpt:9995

29. 0 0 MASQUERADE tcp -- * * 172.18.0.3 172.18.0.3 tcp dpt:8080

30.

31. Chain DOCKER (3 references)

32. pkts bytes target prot opt in out source destination

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

34. 0 0 RETURN all -- br-676bae33ff92 * 0.0.0.0/0 0.0.0.0/0

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

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

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

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

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

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

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

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

43. [root@7dgroup ~]#

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

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

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

  • 在注册时使用的是参数jmxremote.port,然后返回一个新的端口jmxremote.rmi.port。
  • 在调用服务时使用是参数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监控docker中的java应用_显式_04

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

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

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

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

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

    最后留个作业:

  • 如果docker run中如果指定-p 19995:9995,也就是换个端口暴露出去,其他配置都不变。JMX工具还能连得上吗?
  • 如果jmxremote.rmi.port和jmxremote.port不合并,并且同时把两个端口都暴露出去,其他配置都不变。JMX工具还能连得上吗?

  • 上一篇:kvm 安装 windows 虚拟机
    下一篇:没有了
    网友评论