Tomcat で Too many open files 発生しました

| コメントをどうぞ

T/O

冗談です。
どうもDiceK Mikamiです。

さて、表題の件ですが、実際に運用しているAPサーバ(Tomcat)で発生した事態でして、これに関して共有してみたいと思います。
(今日の話しは特に役には立たないので、電車とかで暇なときに読まれるのが良いと思います)

あれはいつのことだったでしょうか。
そう、あれはまだ豊臣秀吉がまだ木下藤吉郎だった頃。。。
社内で運用していたAPサーバが突然の死をむかえたのですが、事態はAPサーバ再起動で事なきを得たのはいいのですが、これが月に一度発生するので堪ったものではありませんでした。
原因を追及したところどうやらOS(Linux)のファイルオープン数が上限に達したためAPサーバがうんともすんとも言わなくなったというものでした。
Tomcatログにも、「 Too many open file 」エラーが出力されていました。

Linuxでは、コネクション自体もファイルとして認識され、コネクションの確立=ファイルオープンと捉えられるようです。
運用していたアプリケーションは、Webアプリケーションであったためある程度コネクションが発生することのは仕方のない事です。
ulimitコマンドを利用して、サクッとこの問題は解決。めでたしめでたし、、、といきたいところでしたが、でるんですよ。
ファイルオープン数の上限値をデフォルトの10倍(10240)にしてもあいつはやってくるんです。
面倒な事この上ないのですが、仕方なく私たちは運用サーバにZabbixを仕掛け、ファイルオープン数を監視する事にしました。

1日で200もファイルをオープンしたまま、コネクションがお亡くなりになっていました。
なんということでしょう!
通常、お亡くなりになってもアプリケーションのVM(今回はJavaアプリなのでJVM)が良きに計らってくれるのですが、コネクションの状態が「 can’t identify protocol 」になるとおしまいです。
(こうした状態確認には、lsofコマンドを使うと大変良いです)
さらっと放置します。
やってくれるな。

しかしながら、私たちにとって運が良かったことは、その他に運用していたサーバではこうした問題が発生していなかったことです。
バージョンの同じJava。
バージョンの同じTomcat。
バージョンの同じMySQL。
バージョンの違うJDBCコネクタ。

!!!!!!

犯人はお前か!
いや、まてまて。
醜いアヒルの子がいたからと言って、それが悪であると決めつけるのは早計。
私たちは腐ったミカンじゃない技術者です。
明確な証拠もないのに犯人を決める訳には参りません。

私はlsofコマンドを昼となく夜となく連打し(lsofはスナップショットしか提供してくれません)、本当にJDBCドライバが犯人なのか地道な捜査を開始しました。
調査しなければならない事は以下の2点です。

  1. MySQLに接続するコネクションがcan’t identify protocolに変化するのか
  2. バージョンの異なるJDBCコネクタで現象が発生するのか

まずは、1点目に関して。
これは現象環境でlsofを連打し、変化するのかを確認するだけです。
コネクションがcan’t identify protocolになると、なにに利用されていたのかを捜索するのは、大変困難な作業です。
そのため連打するしかありません。
ただし占有していたアドレスは保持してくれるため目視での確認は比較的容易です。
案の定、MySQLへのコネクションが変化している事が判明しました。

次に、2点目。
コネクタのバージョンを変えるとどうなるか。
現象環境で利用していたコネクタは「 mysql-connector-java-5.1.12-bin.jar 」でした。
これと最新コネクタである「 mysql-connector-java-5.1.33-bin.jar 」を比較してみます。
ここでは、それぞれを設置した環境にファイルオープン数を取得するようにZabbixを設置し、1日ほど放置します。
放置した結果、最新ではもちろんの事ながら発生せず、利用していたコネクタでは発生しました。
運用サーバのJDBCコネクタを最新に変更して、これで万事解決です。

ここからは後日談。
運用サーバは突然の死をむかえる事なく、元気に動いてくれています。
その後、実際にどのコネクタバージョンから問題が解消されたのかを追加調査しました。
結論だけ書きますと、「 mysql-connector-java-5.1.14-bin.jar 」で解消されておりました。
なるほどやはり問題になっていたので、早期に解決されていたのですね。
最大の問題はリリースノートにも、チケットにもその事実が記載されていない事なんですがね。

今回出演した仕組み

  • OS: CentOS 6.5
  • Java: JDK 7
  • MySQL: MySQL 5.5

頑張った仕組み

  • lsofコマンド
  • psコマンド
  • wcコマンド
  • Zabbix
  • and 俺

やらかした仕組み

  • mysql-connector-java-5.1.12-bin.jar

教訓

ライブラリは最新バージョンを使おう
リリースノートにはきちんと書こう

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>