Thursday, February 3, 2011

Monitoring your Java application with JMX - Part 2

In the Part-1 of this article I explained the fundamentals of JMX monitoring, local and remote monitoring and provided an example on monitoring a java application locally. In Part-2 I'll explain how to monitor it remotely and how to authenticate the monitoring process.

Following system properties need to be present for remote monitoring.
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=portNum where portNum is the port which you want to enable the JMX connection.

You also need to add the follwing two properties.
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false

By default, ssl and authentication is enabled. Therefore if you do not set authenticate=false, application will look for a password file and hence fail to start. If ssl is not set to false, you wont be able to connect without configuring ssl properly.

There is a special scenario where your network interface might be only listening to IPv6 addresses and hence a request from an IPv4 address failing to connect. To get rid of this, you have to add the following property too.
-Djava.rmi.server.hostname=yourIP

Lets try to monitor Tcpmon remotely. When we were monitoring Tcpmon locally we just had to start it and monitor. But in remote scenario, we have to provide the parameters mentioned above. To do this, open TCPMON_HOME/build/tcpmon.sh. It will contain,
java -cp ./tcpmon-1.0.jar org.apache.ws.commons.tcpmon.TCPMon $*

Now, edit it by adding the above parameters. Then it will look like,
java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=port
-Djava.rmi.server.hostname=yourIP -Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false -cp ./tcpmon-1.0.jar org.apache.ws.commons.tcpmon.TCPMon $*

Save tcpmon.sh and run it. You will be successfully able to start Tcpmon. Then start a JConsole from a remote machine. Provide host:port for the remote process and click connect. You will be able to connect to JMX service successfully.


Lets turn to authenticating the monitoring. First, you have to set -Dcom.sun.management.jmxremote.authenticate=true. When this is set, system will be looking for a password file and an access file. You can find these two files (jmxremote.access and jmxremote.password.template) in JDK_HOME/jre/lib/management folder. Copy these two files to a place you refer. Rename jmxremote.password.template to jmxremote.password.

Following is a section extracted from the password file.
# Following are two commented-out entries.  The "monitorRole" role has
# password "QED". The "controlRole" role has password "R&D".
#
monitorRole QED
controlRole R&D

You can define role names (usernames) and passwords as shown above. Actions which are allowed to these roles are defined in the jmxremote.access file. Shown below is a section extracted from it.# Default access control entries:
# o The "monitorRole" role has readonly access.
# o The "controlRole" role has readwrite access and can create the standard
# Timer and Monitor MBeans defined by the JMX API.

monitorRole readonly
controlRole readwrite

You have to restrict access (make read-write-only by the owner) to the jmxremote.password file by,
chmod 0600 jmxremote.password
Then if you ls -l the files, you should see,
-rw-r--r-- 1 amila amila 3896 2011-01-17 17:45 jmxremote.access
-rw------- 1 amila amila 2854 2011-01-17 17:47 jmxremote.password
After that you have to set the system properties to point to the password and access files. Following are the properties.
-Dcom.sun.management.jmxremote.password.file=/path/to/jmxremote.password/file
-Dcom.sun.management.jmxremote.access.file=/path/to/jmxremote.access/file

Lets turn back to our Tcpmon monitoring again. Add the above two properties to tcpmon.sh and make authenticate=true. Then. tcpmon.sh should look like,
java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=port
-Djava.rmi.server.hostname=yourIP -Dcom.sun.management.jmxremote.authenticate=true
-Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.password.file=/path/to/jmxremote.password/file
-Dcom.sun.management.jmxremote.access.file=/path/to/jmxremote.access/file -cp ./tcpmon-1.0.jar org.apache.ws.commons.tcpmon.TCPMon $*
Now, save tcpmon.sh and run it. Start a JConsole from a remote machine. Provide the host:port parameters, username and password and click connect. You will be able to successfully monitor Tcpmon remotely. You can try out the difference between the two access roles defined in the jmxremote.access file.

monitorRole readonly
controlRole readwrite


If you log in as the monitorRole, you will be only allowed to monitor. If you try to carry out controlRole tasks, you will be provided with a warning message as shown below.

So, now you are able to monitor your Java application using JMX successfully. For a quick recap, following are the necessary system properties to monitor it remotely.
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=portNum
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=true
-Djava.rmi.server.hostname=yourIP
-Dcom.sun.management.jmxremote.password.file=/path/to/jmxremote.password/file
-Dcom.sun.management.jmxremote.access.file=/path/to/jmxremote.access/file
Find more details on JMX from here.

3 comments:

  1. I have read documentation about jmx console and it is quite clear but a complete example like this is always useful. Thanks

    ReplyDelete
  2. Hi Amila, Found it after I'm done with my project stuff ... ;)


    But it is a very nice detailed explanation with example ... very helpful to a novice ... thanks.

    -Krishna.

    ReplyDelete
  3. Hi Fran & Krishna,

    Thanks for your feedbacks.

    Amila.

    ReplyDelete