Monitorer tomcat/java/bloat avec collectd

collectd c'est le bien, la nouvelle hype du monitoring qui fait des graphes zwip-zwip dissaidor compliant. Malheureusement, des fois les dissaidors ils font de la merde et on se retrouve avec des blo^Whorreu^Wmachi^Wtomcat en prod. Donc il faut un moyen de les monitorer pour pouvoir dire 'zyva tavu toute la ram qu'il bouffe lui'.

Et la, j'ai pas trouvé de doc toute faite bien précise de bout en bout, d'ou ce blurb.

Tomcat

Ici, debian lenny/tomcat 5.5 classique.

jmx

Déja, faut dire a tomcat qu'on va utiliser un machin nommé jmx pour regarder les indicateurs™. Donc, dans /etc/default/tomcat5.5 on ajoute tout ca a JAVA_OPTS.

JAVA_OPTS="-Dcom.sun.management.jmxremote \
     -Dcom.sun.management.jmxremote.port=7091 \
     -Dcom.sun.management.jmxremote.authenticate=false \
     -Dcom.sun.management.jmxremote.ssl=false"

La, bien évidemment, on est sur un serveur en remote, donc pas de X, donc pas d'utilisation de jconsole. Pour faire un test de jmx en cli-only (tel le vrai admin barbu) on pourra recourir a jmxterm ou cmdline-jmxclient.

$java -jar jmxterm-1.0-alpha-4-uber.jar -l localhost:7091
$java -jar cmdline-jmxclient-0.10.3.jar - localhost:7091

Maintenant, on “”“sécurise”“” un peu tout ca via un peu de user/pass/auth sur jmx:

#JAVA_OPTS dans /etc/default/tomcat5.5
....
        -Dcom.sun.management.jmxremote.authenticate=true \
        -Dcom.sun.management.jmxremote.access.file=../conf/jmxremote.access \
        -Dcom.sun.management.jmxremote.password.file=../conf/jmxremote.password \
        -Dcom.sun.management.jmxremote.ssl=false \
....
#cat /var/lib/tomcat5.5/conf/jmxremote.access 
monitorUser readonly
#cat /var/lib/tomcat5.5/conf/jmxremote.password 
monitorUser ZOMGPASSWORD!
#chmod 600 /var/lib/tomcat5.5/conf/jmxremote.*
#chown tomcat55 /var/lib/tomcat5.5/conf/jmxremote.*
#/etc/init.d/tomcat5.5 restart

Et on reteste:

#java -jar jmxterm-1.0-alpha-4-uber.jar -u monitorUser -p ZOMGPASSWORD! -l localhost:7091

security manager

Dans les trucs qui hérissent les poils, y'a ce #@!#@!$@! de security manager, auquel il faut dire fonction par fonction ce qu'on autorise. Pour mon cas il faudra:

#cat /etc/tomcat5.5/policy.d/70jmx.policy 

grant principal javax.management.remote.JMXPrincipal "monitor"
{
   permission java.net.SocketPermission "*", "listen,accept,resolve";
   permission javax.management.MBeanPermission "*", "queryNames,getAttribute";
};
#/etc/init.d/tomcat5.5 restart

Ainsi, plus d'insultes telles que:

collectd[30053]: GenericJMXConfMBean: queryNames failed: java.security.AccessControlException: access denied (javax.management.MBeanPermission -#-[-] queryNames)
collectd[30053]: GenericJMXConfMBean: queryNames failed: java.rmi.ConnectException: Connection refused to host: 10.0.0.4; nested exception is : java.net.ConnectException: Connection refused
collectd[2036]: GenericJMXConfValue.query: getAttribute failed: java.security.AccessControlException: access denied (javax.management.MBeanPermission sun.management.MemoryPoolImpl#Usage[java.lang:name=PS Eden Space,type=MemoryPool] getAttribute)

Collectd

Coté collectd, on se basera sur l'excellente doc du site de collectd, avec cet exemple de conf (aussi dispo dans /usr/share/doc/collectd-core/examples/GenericJMX.conf)

Donc les modifs importantes du /etc/collectd/collectd.conf sont:

LoadPlugin java
<Plugin "java">
#  JVMArg "-verbose:jni"
  JVMArg "-Djava.class.path=/usr/share/collectd/java/"
  LoadPlugin "org.collectd.java.GenericJMX"
...
plein de definitions de MBeans auquel on bite rien
...

    #####################
    # Connection blocks #
    #####################
    <Connection>
      ServiceURL "service:jmx:rmi:///jndi/rmi://tomcat_host:7091/jmxrmi"
      User "monitorUser"
      Password "ZOMGPASSWORD!"
      Host "nom-pour-host-collectd"
      Collect "classes"
      Collect "compilation"
      Collect "garbage_collector"
      Collect "memory"
      Collect "memory_pool"
      Collect "catalina/global_request_processor"
      Collect "catalina/detailed_request_processor"
      Collect "catalina/thread_pool"
    </Connection>
  </Plugin>
</Plugin>

ne pas oublier le classpath pointant vers /usr/share/collectd/java pour éviter le message d'erreur suivant :

cjni_init_native: Cannot find API class `org/collectd/api/Collectd'.

Ah, et éventuellement, ne pas oublier aptitude install openjdk-6-jre-headless pour éviter l'erreur cryptique suivante (java.so dépend de libjvm.so) :

lt_dlopen (/usr/lib/collectd/java.so) failed: file not found

Enfin, vous pouvez maintenant faire un peu de recursive loling en monitorant collectd via collectd, vu qu'il charge une jvm et bouffe du coup allégrement 1.7Gigowatt de RAM.

JAVA, TU PUES~!@!#

unix/collectd_tomcat.txt · Last modified: 2010/10/04 15:15 by gast0n