きっと何者にもなれないSEの記録帳

日々で得たIT技術を記録していきます。

マシン性能に異常が見られないパフォーマンス問題(Java製Webアプリ+MySQL)

Java製Webアプリ+MySQL上で発生したパフォーマンス問題についてです。
負荷分散を行うシステム構成で、APサーバが2台の場合、性能に問題なし。APサーバが1台の場合、性能が悪化するという問題が起こりました。ただし、CPU使用率は限界に達していない。JVMのメモリ量は余裕がある。NW帯域は問題なしという状態。
 
結論からいうと、DBのコネクションプールの処理でスレッドに対して同期処理を行っていて、多くのスレッドで待ちが発生していたためでした。
単純にスレッドが待っている状態なので、CPUもメモリも問題ないわけです。
 
この問題にどのように対応したかについての記録です。
 
1.スレッドダンプを取りました。
2.JDBCドライバの設定をいじり、性能が向上することを確認しました。
 
スレッドダンプを取る
JDK標準で用意されているjstackコマンドを使用しました。
 
今回の場合、tomcatを使用しています。tomcatのプロセスIDを調べて、下記のコマンドでスレッドダンプを取りました。
 
jstack プロセスID

スレッドダンプの解析には下記を使用しました。
 
 
侍を使うと同期待ちを行っているスレッドがひと目でわかります。また、スタックトレースからDBのコネクションプールを行っている処理で多くのスレッドが同期待ちしていました。

JDBCドライバの設定
スレッドダンプを取り、多くのスレッドが同期待ちを起こしていることは確認できました。しかし、それが性能悪化の原因であるかは性能を改善させることで証明するしかありません。
 
アプリケーションとDBとのやりとりを速めることができれば、各スレッドの処理を速くすることができるので、性能を改善することができると判断しました。
 
色々調べてみると、DB提供元から用意されているJDBCドライバにパフォーマンスに関わる設定が存在することを知りました。
 
今回はMySQLを使用しています。性能に直結したJDBCドライバの設定は下記です。
 
トランザクション分離レベルの設定を毎回行わない。autocommitの命令を排除するということを行いました。
プロパティ名 デフォルト値 設定値
alwaysSendSetIsolation true false
elideSetAutoCommits false true

MySQLJDBCドライバ設定は下記を参考にしました。
 
 
 
上記設定を行うことで、APサーバ1台でもAPサーバ2台と同等の性能を発揮することができました。
 
所感
今回の調査をするにあたり、スレッドダンプを取るということを始めて行いました。意外に簡単に取得できるものだということを実感しました。また、スレッドダンプを取ることが原因を突き止めるきっかけにもなったので、今後はスレッドダンプを取るということも初期段階の調査に加えるべきと感じました。