通过JMX访问docker容器中运行的tomcat

我想通过JMX获得tomcat的性能。 Tomcat版本是7,Java版本是1.7.0_79。

Tomcat在Docker的容器上运行。 端口映射已经build立如下。

docker run -itd -p 18080:8080 -p 19998:19998 -p 62911:62911 sad_jang2 bash 

在tomcat容器中,setevn.sh是在path/ tomcat_home / bin /中创build的,具有以下内容。

 export JAVA_OPTS=" -Xdebug -Xrunjdwp:transport=dt_socket,address=62911,server=y,suspend=n -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=19998 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=172.17.0.16" 

我写了一个简单的java代码

 JMXServiceURL serviceURL = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + "172.17.0.16"+ ":" + "19998" + "/jmxrmi"); JMXConnector connector = JMXConnectorFactory.connect(serviceURL, null); MBeanServerConnection mbsc = connector.getMBeanServerConnection(); 

并可以通过JMX获取相关的值。

但是,我运行这个代码在我的桌面与docker主机的地址和19998端口,如

 JMXServiceURL serviceURL = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + "10.70.1.5"+ ":" + "19998" + "/jmxrmi"); 

控制台显示以下消息

 java.rmi.ConnectException: Connection refused to host: 172.17.0.16; nested exception is: java.net.ConnectException: Connection timed out: connect at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619) at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216) at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202) at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:130) at javax.management.remote.rmi.RMIServerImpl_Stub.newClient(Unknown Source) at javax.management.remote.rmi.RMIConnector.getConnection(RMIConnector.java:2432) at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:308) at javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:270) at utility.GetStatistic.getTomcatStats(GetStatistic.java:84) at exec.Main.main(Main.java:53) Caused by: java.net.ConnectException: Connection timed out: connect at java.net.DualStackPlainSocketImpl.connect0(Native Method) at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589) at java.net.Socket.connect(Socket.java:538) at java.net.Socket.<init>(Socket.java:434) at java.net.Socket.<init>(Socket.java:211) at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40) at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:148) at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613) ... 9 more 

使用浏览器连接URL http://10.70.1.5:18080可以显示tomcat的根页面。

任何人都可以给任何build议? 谢谢。

以下是我成功用于通过JMX监视ZooKeeper容器的标志:

-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.port=9010 -Dcom.sun.management.jmxremote.rmi.port=9010 -Djava.rmi.server.hostname=192.168.1.4 -Dcom.sun.management.jmxremote.ssl=false

所以区别在于这个条目-Dcom.sun.management.jmxremote.rmi.port将RMI端口修复为与JMX端口相同。

有了这个,我可以只是docker run -p 9010:9010 ...一切都很好。

当您在Docker机器中运行该容器时,这不起作用 – 在VirtualBox中。 我不知道我应该添加到java.rmi.server.hostname什么样的地址,因为当我添加的Docker容器的外部IP,我从我的主机连接,它不起作用。 所以基本上情况就像HOST —>(MACHINE — CONTAINER),我无法从HOST到达CONTAINER。

我不确定是否有必要,但我会build议添加到您的其他选项-Djgroups.bind_addr=172.17.0.16 。 另外我很确定,这种select应该可以去CATALINA_OPTS,而不是JAVA_OPTS,但这不应该有所作为。 我注意到的另一件事是您定义的rmi服务器主机名称与JMXServiceURL构造函数中的名称不同。 我不是docker专家,但不应该这样做吗?

这configuration为我工作:

 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.port=10005 -Dcom.sun.management.jmxremote.rmi.port=10005 -Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote.ssl=false 

最重要的部分是使用本地环回地址configurationrmi服务器主机名。 如果我使用0.0.0.0,我无法通过SSH隧道到达暴露的本地端口, 127.0.0.1一切工作正常

注意 :如果你在virtualbox里面运行docker的话是不一样的…你必须使用virtualbox给你的ip。