「这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战」
一、前言
今天在配置 docker 和 JMX 监控的时候,看到有一个细节和非容器环境中的 JMX 配置不太一样。所以在这里写一下,以备其他人查阅。
二、遇到的问题
1、问题现象
一般情况下,我们配置 JMX 只要写上下面这些参数就可以了。
以下是无密码监控时的 JMX 配置参数(有密码监控的配置和常规监控无异)
1 | bash复制代码-Dcom.sun.management.jmxremote |
但是在 docker 容器中这样配置的时候,会出现这个错误。
2、问题分析
这里就要说明一下逻辑了。为什么会这样呢?
先看 docker 环境的网络结构。
容器使用默认的网络模型,就是 bridge 模式。在这种模式下是 docker run 时做的 DNAT 规则,实现数据转发的能力。所以我们看到的网络信息是以下这样的:
docker 中的网卡信息:
1 | bash复制代码[root@f627e4cb0dbc /]# ifconfig |
docker 中的路由信息:
1 | bash复制代码[root@a2a7679f8642 /]# netstat -r |
宿主机上的对应网卡信息:
1 | bash复制代码docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 |
宿主机上的路由信息:
1 | bash复制代码[root@7dgroup ~]# netstat -r |
所以宿主机和容器是可以直接通信的,即便端口没有映射出来。如下所示:
1 | bash复制代码[root@7dgroup ~]# telnet 172.18.0.3 8080 |
另外,因为是桥接的,宿主机上还有类似 veth0b5a080 的虚拟网卡设备信息,如:
1 | bash复制代码eth0b5a080: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 |
这就是虚拟网卡对 veth pair,docker 容器里一个,宿主机一个。 在这种模式下,有几个容器,主机上就会有几个 veth 开头的虚拟网卡设备。
但是如果不是宿主机访问的话,肯定是不通的。如下图所示:
当我们用监控机 访问的时候,会是这样的结果:
1 | bash复制代码Zees-Air-2:~ Zee$ telnet <serverip> 8080 |
因为 8080 是容器开的端口,并不是宿主机开的端口,其他机器是访问不了的。 这就是为什么要把端口映射出来给远程访问的原因,映射之后的端口,就会有 NAT 规则来保证数据包可达。
查看下 NAT 规则,就知道。如下:
1 | bash复制代码[root@7dgroup ~]# iptables -t nat -vnL |
我们看到了宿主机的 91 端口的数据会传给 172.18.0.2
的 80 端口。宿主机的 3307 端口会传给 172.18.0.4
的3306 端口。
啰啰嗦嗦说到这里,那和 JMX 有啥关系。苦就苦在,JMX 是这样的:
在注册时使用的是参数 jmxremote.port
,然后返回一个新的端口 jmxremote.rmi.port
。
在调用服务时使用是参数 jmxremote.rmi.port
。 前面提到了,因为 docker 在 bridge 模式下端口是要用 -p 显式指定的,不然没 NAT 规则,数据包不可达。所以在这种情况下,只能把 jmxremote.rmi.port
也暴露出去。所以必须显式指定。因为不指定的话,这个端口会随机开。随机开的端口又没 NAT 规则,所以是不通的了。
三、解决方案
所以,这种以上情况只能指定 jmxremote.rmi.port
为固定值,并暴露出去。 配置如下:
1 | bash复制代码-Dcom.sun.management.jmxremote |
像上面的设置就是两个都是 9995,这样是允许的,这种情况下注册和调用的端口就合并了。
再启动 docker 容器的时候,就需要这样了。
1 | bash复制代码docker run -d -p 9003:8080 -p 9995:9995 --name 7dgroup-tomcat5 |
然后就可以连接上 JMX 的工具了。
在有防火墙和其他的设备的网络环境中,也有可能出同样的问题。明白了JMX 的注册调用逻辑之后,就可以解决各种类似的问题了。
网络链路是做性能分析的人必须想明白的技术点,所以前面说了那么多内容。
四、总结
这里对于 JMX 工具的选择啰嗦两句。有人喜欢花哨的,有人喜欢简单的,有人喜欢黑窗口的。我觉得工具选择的时候,要看适用情况,在性能分析的时候,一定要选择合适的工具,而不是选择体现技术高超的工具。
最后留个作业:
- 如果
docker run
中如果指定-p 19995:9995
,也就是换个端口暴露出去,其他配置都不变。JMX 工具还能连得上吗? - 如果
jmxremote.rmi.port
和jmxremote.port
不合并,并且同时把两个端口都暴露出去,其他配置都不变。JMX 工具还能连得上吗?
有兴趣的可以自己尝试下哦。
本文转载自: 掘金