简体   繁体   中英

Access tomcat running in docker container by JMX

I want to get tomcat's performance by JMX. Tomcat version is 7 and Java version is 1.7.0_79.

Tomcat runs on the docker's container. The port mapping has set up by the following.

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

In the tomcat container, setevn.sh was created in the path, /tomcat_home/bin/ with the following content.

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"

I write a simple java code as

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();

and can get related values by JMX.

However, I run this code in my desktop with the docker host's address and 19998 port such as

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

The console displayed the following message

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

Using the browser to connect the URL http://10.70.1.5:18080 can show the tomcat root's page.

Can anyone give any suggestions? Thanks.

Here's the flags I've successfully used for monitoring my ZooKeeper container via JMX:

-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=0.0.0.0
-Dcom.sun.management.jmxremote.ssl=false

So the difference would be this entry -Dcom.sun.management.jmxremote.rmi.port which is fix the RMI port to be the same as JMX port.

With this I can just docker run -p 9010:9010 ... and everything is fine for me.

This does not work when you run that container in Docker machine - in VirtualBox. I am not sure what kind of address I should add to java.rmi.server.hostname because when I add there external IP of the Docker container I am connecting from my host, it does not work. So basically situation is like HOST ---> (MACHINE --- CONTAINER) and I can not reach it from HOST to CONTAINER.

I'm not sure if it's necessary but I would recommend adding this to your additional options -Djgroups.bind_addr=172.17.0.16 . Also I'm pretty sure that this kind of options should probably go to CATALINA_OPTS and not JAVA_OPTS but that shouldn't make a difference. Another thing that I noticed is that the rmi server host name you defined is different than the one in the JMXServiceURL constructor. I'm no docker expert but shouldn't this be identical?

This config worked for me:

-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

The important part was to to configure the rmi server hostname with the local loopback address. If i used 0.0.0.0 i wasn't able to reach the exposed port localy via an SSH Tunnel, with 127.0.0.1 everything worked fine .

Note : if you're running docker inside virtualbox things are different... you have to use the ip which virtualbox gives you here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM