Showing posts with label Tomcat. Show all posts
Showing posts with label Tomcat. Show all posts

2011/02/09

Monitoring Tomcat with Jmxterm and Python

I needed to collect statistics related to connections in Tomcat. The goal was to use some command line tool to make dumping and post-processing of acquired data as simple as possible. It seems that jmxterm fitts well into these requirements. Following text represents short HOWTO for monitoring some of Tomcat's JMX attributes using jmxterm.
  1. Enable JMX in your Tomcat, e.g. by adding following parameters to its java command line.
            -Dsun.management.jmxremote -Dcom.sun.management.jmxremote.port=3993
            -Dcom.sun.management.jmxremote.ssl=false
            -Dcom.sun.management.jmxremote.authenticate=false
    As you see this settings turns off  both SSL and authentication, to make this simplem, although not secure.
    Jmxterm does not support SSL yet, password-based authentication in command open is supported (use help open in jmxterm shell for more info).
  2. Download jmxterm from http://sourceforge.net/projects/cyclops-group/files/jmxterm/
  3. Start in interactive mode to test commands:
    java -jar jmxterm-${version}-uber.jar
    (for ${version} substitute current version of jxmterm, e.g. "1.0-alpha-4")
  4. Run commands to get desired data
    1. open localhost:3993
    2. Restricts output of following commands to given domain - select domain: domain Catalina.
    3. Now you can list beans:
      beans
    4. now the domain is set and we get values of some attributes:
      • get -b Catalina:port=80,type=Connector acceptCount
        get -b Catalina:port=80,type=Connector acceptCount
        #mbean = Catalina:port=80,type=Connector:
        acceptCount = 100;
      • get -b name=http-80,type=ThreadPool maxThreads
        get -b name=http-80,type=ThreadPool maxThreads
        #mbean = Catalina:name=http-80,type=ThreadPool:
        maxThreads = 40;
      • get -b name=http-80,type=ThreadPool currentThreadCount
        get -b name=http-80,type=ThreadPool currentThreadCount
        #mbean = Catalina:name=http-80,type=ThreadPool:
        currentThreadCount = 15;
      • get -b name=http-80,type=ThreadPool currentThreadsBusy
        get -b name=http-80,type=ThreadPool currentThreadsBusy
        #mbean = Catalina:name=http-80,type=ThreadPool:
        currentThreadsBusy = 2;
      • get -b Catalina:host=localhost,path=${webapp_context},type=Manager activeSessions
        get -b Catalina:host=localhost,path=${webapp_context},type=Manager activeSessions
        #mbean = Catalina:host=localhost,path=${webapp_context},type=Manager:
        activeSessions = 3;
    5. Put commands in file and run this scripts in non-interactive way
      java -jar jmxterm-${version}-uber.jar -n
      or
      java -jar jmxterm-${version}-uber.jar -n -i jmx_script

      content of the file jmx_script:
      open localhost:3993
      get -d Catalina -b Catalina:port=80,type=Connector acceptCount
      get -d Catalina -b name=http-80,type=ThreadPool maxThreads
      get -d Catalina -b name=http-80,type=ThreadPool currentThreadCount 
      get -d Catalina -b name=http-80,type=ThreadPool currentThreadsBusy
      quit

      Output:


      Welcome to JMX terminal. Type "help" for available commands.
      #Connection to localhost:3993 is opened
      #mbean = Catalina:port=80,type=Connector:
      acceptCount = 100;

      #mbean = Catalina:name=http-80,type=ThreadPool:
      maxThreads = 40;

      #mbean = Catalina:name=http-80,type=ThreadPool:
      currentThreadCount = 18;

      #mbean = Catalina:name=http-80,type=ThreadPool:
      currentThreadsBusy = 5;

      #bye

note #1 : if domain si not set, you must give it  to get command as parameter:
get -d Catalina -b ${bean_name} ${attribute_name}

Wrapping in Python

The problem with jmxterm si that its startup time is really long - even several seconds. Also connecting to process can take second or two. The reponsivness is good so if you need it for periodic monitoring, you would like to start it and connect and then fire requests when you need the data. After trying some approaches I settled on Python pexpect for this (script reduced to minimum):
import time
import pexpect

connection = "localhost:3993"
connection_timeout = 2

jmxterm = pexpect.spawn("java -jar jmxterm-1.0-alpha-4-uber.jar")
jmxterm.expect_exact("$>") # got prompt, we can continue
jmxterm.sendline("open " + connection)
jmxterm.expect_exact("#Connection to "+connection+" is opened", connection_timeout)

jmxterm.sendline("get -d Catalina -b name=http-80,type=ThreadPool currentThreadCount")

response_lines = []
response_lines.append(jmxterm.readline())
response_lines.append(jmxterm.readline())
response_lines.append(jmxterm.readline())
response_lines.append(jmxterm.readline())

result = response_lines[3].replace(";"," ").strip().split(" ")
del result[1]
name,value = result

print "["+time.ctime()+"]", name, "=", value
jmxterm.sendline("quit")

2010/02/10

Apache-Tomcat Communication via mod_jk

Ever wondered why to use mod_jk and how to set it up? The reasons why are simple - Tomcat guys recommend it as more mature.

It certainly has better logging then mod_ajp_proxy and that helps alot during troubleshooting or performance tuning. The ability to set max packet size above 8kB is also a good point for some deployments. As for performance, some tests showed slight advantage of mod_jk to mod_ajp_proxy, but the main seemed to be the usage of Tomcat's native module regardless of AJP module used.

LoadModule jk_module /usr/lib/httpd/modules/mod_jk.so

# points to a file that provides a mapping between a worker name and a valid worker type
JkWorkersFile /etc/httpd/conf/worker.properties
JkLogFile /var/log/httpd/mod_jk.log

# allows log levels: debug, info, error
JkLogLevel   info
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
JkRequestLogFormat      "%w %V %T"

# JkOptions - see http://tomcat.apache.org/connectors-doc/reference/apache.html

<Location /jkstatus/>
 JkMount status
 # Order deny,allow
 # Deny from all
 # Allow from 127.0.0.1
 Allow from all
</Location>

<VirtualHost *:80>
  # which URI contexts are sent to a ASF Tomcat worker - exact, context or suffix match
  JkMount /* tomcat1
</VirtualHost>

Note: JkMount must be defined in VirtualHost to work.

worker.properites:

worker.list=tomcat1
worker.tomcat1.type=ajp13
worker.tomcat1.host=localhost
worker.tomcat1.port=8009

## when using mpm prefork, the pool_size should be set to "1"
worker.tomcat1.connection_pool_size=1
worker.tomcat1.connection_pool_timeout=600
worker.tomcat1.socket_keepalive=1

max_packet_size=65536


JkWorkerProperty directive allows to move content of the worker.properties file to apache config.