Zabbix から Spring Boot アプリケーションのデータベース接続状況を取得する
イートスマートでは、Zabbixで各サーバやコンテナのリソースを管理し、必要に応じてアラートを飛ばしています。 先日、データベースの接続数が増えてきたのでコンテナごとに接続数を把握しようと思い、Zabbixのテンプレートを使い以下の2つの項目を監視するようにしました。
jmx["Catalina:class=javax.sql.DataSource,context=/,host=localhost,name=\"database\",type=DataSource",numActive] jmx["Catalina:class=javax.sql.DataSource,context=/,host=localhost,name=\"database\",type=DataSource",numIdle]
それぞれ接続数とアイドル数です。 Tomcatを利用するアプリケーションは問題なく取得出来ましたが、Spring Bootを利用するアプリケーション(以降Spring Bootアプリ)で取得出来ませんでした。 Spring Bootアプリに必要となった設定をまとめます。Spring Bootのバージョンは少し古く1.5.2となります。
データベス接続情報
spring: profiles: stg datasource: driverClassName: org.postgresql.Driver url: jdbc:postgresql://xxxx.xxxx.xxxx:5432/xxxx username: xxxx password: xxxx jmx-enabled: true
新たに spring.datasource.jmx-enabled: true という設定が必要になりました。 application.ymlへは、以下のように追加しました。
起動オプション
java -Dcom.sun.management.jmxremote \ -Dcom.sun.management.jmxremote.port=[JMXポート番号] \ -Dcom.sun.management.jmxremote.authenticate=false \ -Dcom.sun.management.jmxremote.ssl=false \ -Dcom.sun.management.jmxremote.rmi.port=[JMXポート番号] \ -Djava.rmi.server.hostname=[ホストIPアドレス] \ ....
アプリケーション起動時に、JMXで利用するポート番号等の設定を追加しました。 ホストのIPアドレスを指定しているのは、Dockerコンテナで起動する場合にポートフォワードでは動かないためです。 そのたりは以下に書いています。
動作確認
上記の設定を行い起動すると、ログに以下のようにMBeanの登録情報が出力されます。
2019-11-19 16:22:31.077 INFO 15636 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 2019-11-19 16:22:31.079 INFO 15636 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'dataSourceMBean' has been autodetected for JMX exposure 2019-11-19 16:22:31.084 INFO 15636 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located MBean 'dataSourceMBean': registering with JMX server as MBean [org.apache.tomcat.jdbc.pool.jmx:name=dataSourceMBean,type=ConnectionPool]
この情報をもとに接続します。接続には、javaから手軽に利用できる jmxterm を利用します。
java -jar jmxterm-1.0.0-uber.jar $>open xxx.xxx.xxx.xxx:12345 #Connection to xxx.xxx.xxx.xxx:12345 is opened $>info -b org.apache.tomcat.jdbc.pool.jmx:name=dataSourceMBean,type=ConnectionPool #mbean = org.apache.tomcat.jdbc.pool.jmx:name=dataSourceMBean,type=ConnectionPool #class name = org.apache.tomcat.jdbc.pool.jmx.ConnectionPool # attributes %0 - AbandonWhenPercentageFull (int, rw) %1 - AccessToUnderlyingConnectionAllowed (boolean, rw) %2 - Active (int, r) %3 - AlternateUsernameAllowed (boolean, rw) %4 - BorrowedCount (long, r) %5 - CommitOnReturn (boolean, rw) %6 - ConnectionProperties (java.lang.String, rw) %7 - CreatedCount (long, r) %8 - DataSource (java.lang.Object, rw) %9 - DataSourceJNDI (java.lang.String, rw) %10 - DbProperties (java.util.Properties, rw) %11 - DefaultAutoCommit (java.lang.Boolean, rw) %12 - DefaultCatalog (java.lang.String, rw) %13 - DefaultReadOnly (java.lang.Boolean, rw) %14 - DefaultTransactionIsolation (int, rw) %15 - DriverClassName (java.lang.String, rw) %16 - FairQueue (boolean, rw) %17 - Idle (int, r) %18 - IgnoreExceptionOnPreLoad (boolean, rw) %19 - InitSQL (java.lang.String, rw) %20 - InitialSize (int, rw) %21 - JdbcInterceptors (java.lang.String, rw) %22 - JdbcInterceptorsAsArray ([Lorg.apache.tomcat.jdbc.pool.PoolProperties$InterceptorDefinition;, r) %23 - JmxEnabled (boolean, rw) %24 - LogAbandoned (boolean, rw) %25 - LogValidationErrors (boolean, rw) %26 - MaxActive (int, rw) %27 - MaxAge (long, rw) %28 - MaxIdle (int, rw) %29 - MaxWait (int, rw) %30 - MinEvictableIdleTimeMillis (int, rw) %31 - MinIdle (int, rw) %32 - Name (java.lang.String, rw) %33 - NumActive (int, r) %34 - NumIdle (int, r) %35 - NumTestsPerEvictionRun (int, rw) %36 - Password (java.lang.String, rw) %37 - PoolName (java.lang.String, r) %38 - PoolSweeperEnabled (boolean, r) %39 - PropagateInterruptState (boolean, rw) %40 - ReconnectedCount (long, r) %41 - ReleasedCount (long, r) %42 - ReleasedIdleCount (long, r) %43 - RemoveAbandoned (boolean, rw) %44 - RemoveAbandonedCount (long, r) %45 - RemoveAbandonedTimeout (int, rw) %46 - ReturnedCount (long, r) %47 - RollbackOnReturn (boolean, rw) %48 - Size (int, r) %49 - SuspectTimeout (int, rw) %50 - TestOnBorrow (boolean, rw) %51 - TestOnConnect (boolean, rw) %52 - TestOnReturn (boolean, rw) %53 - TestWhileIdle (boolean, rw) %54 - TimeBetweenEvictionRunsMillis (int, rw) %55 - Url (java.lang.String, rw) %56 - UseDisposableConnectionFacade (boolean, rw) %57 - UseEquals (boolean, rw) %58 - UseLock (boolean, rw) %59 - Username (java.lang.String, rw) %60 - ValidationInterval (long, rw) %61 - ValidationQuery (java.lang.String, rw) %62 - ValidationQueryTimeout (int, rw) %63 - Validator (org.apache.tomcat.jdbc.pool.Validator, rw) %64 - ValidatorClassName (java.lang.String, rw) %65 - WaitCount (int, r) # operations %0 - void checkAbandoned() %1 - void checkIdle() %2 - java.lang.Boolean isDefaultAutoCommit() %3 - java.lang.Boolean isDefaultReadOnly() %4 - void purge() %5 - void purgeOnReturn() %6 - void resetStats() %7 - void testIdle() # notifications %0 - javax.management.Notification(INIT FAILED,CONNECTION FAILED,CONNECTION ABANDONED,SLOW QUERY,FAILED QUERY,SUSPECT CONNECTION ABANDONED,POOL EMPTY,SUSPECT CONNECTION RETURNED)
この出力内容から、今回必要なものが NumActive と NumIdle ということがわかったので、Spring Bootアプリ用のテンプレートを作成し、以下の2つの項目を監視するようにしました。
jmx["org.apache.tomcat.jdbc.pool.jmx:name=dataSourceMBean,type=ConnectionPool",NumActive] jmx["org.apache.tomcat.jdbc.pool.jmx:name=dataSourceMBean,type=ConnectionPool",NumActive]
まとめ
以上の作業で、イートスマートで利用しているコンテナのデータベース接続数を把握することが出来るようになりました。 実際の利用状況と照らし合わせ、コンテナの最小アイドル数が多かったので、減らすことで問題への対処を行うことが出来ました。