😇
ファイルディスクリプタが増え続けてサーバーが落ちてしまう。
新規のサービスを立ち上げて、しばらく運用していて特にトラブルがなかったのですが ある日いつものようにサービスを覗いたらサーバーが死んでいました。目撃するととても辛い5xx エラーというやつです。ひとまず再起動して事なきを得たものの突発的なアクセスの増加や負荷の重い処理が走っていたなどはなく どうにもわからないままその日が終わりました。数日間は何事もなく過ぎたのですが(その間も調べていたものの見当がついていなかった) 原因が究明できていないので、案の定また落ちてしまいました。そして、またまた調べていくとようやく行き当たりました。
$ sudo ls /proc/769506/fd | wc -l
110
$ sudo ls /proc/769506/fd | wc -l #30分ほど経って
120
$ sudo ls /proc/769506/fd | wc -l #さらに経って
200
ファイルディスクリプタが増えていっています。どういうことでしょうか。以下のようなsocketが大量に溜まっていて大変怪しいですね。
lrwx------ 1 root root 64 Dec 3 06:29 3 -> 'socket:[19708828]'
この類の時は、たいていなんらかの形でDBとのコネクションを閉じ忘れてて握っていることが多いです。(私はたまにやってしまいます。) アプリケーションコードを覗いてみます。(ダミーです)
tx := db.Begin()
res := tx.Create(...)
if err == nil {
// <======= ここで return する前に transactionをComitして閉じなくてはいけない
return nil
}
まさになっていました。非常に残念ですね。毎日寝る前に明日は落ちませんようにと祈っていましたが、もう少し自信を持って寝られるかもしれません。しかし、このようなミスをするようでは寝てはいけないのかもしれませんね。
ちなみに、サービスインしてしばらく何も起きなかったのは
- アクセス数が少なくてFDが枯渇するまでに猶予があった
- 頻繁にデプロイしていたので、アプリケーションが再起動されていたためFDの数がリセットされていた
- そもそも上記のようなコードが入ってしまったのがサービス開始してからしばらく経ってからだった
というような点によるものです。一人開発だと、レビューしてもらえる人がいない。というのは言い訳ですが、気をつけていきたいと思いました。
Discussion