mod_proxy_balancerで503がくせになった時のメモ

またあるかもしれないのでメモっとく。

エラーの始まり

先日DBの障害でバックエンドにDB接続待ちのプロセスがあふれかえったのを機に、その問題が解消した後もサイトが503エラーをたまに吐くようになった。
mod_proxy_balancerを利用したロードバランサーには以下のようなエラーログ。

[Thu Dec 15 12:00:00 2010] [error] (113)No route to host: proxy: HTTP: attempt to connect to 192.168.1.101:80 (192.168.1.101:80) failed
[Thu Dec 15 12:00:00 2010] [error] ap_proxy_connect_backend disabling worker for (192.168.1.101)

しかしロードバランサー側にもバックエンド側にも特に問題があるようには見えない。
なのになぜかこうしたエラーが出て、ロードバランサー的にはバックエンドをエラー状態とみなしてしまうと言う。

ぐぐってみるとけっこうありふれた問題らしい。
しかし解決した例が見つからない。みんな原因が特定できずに困っている。

このメッセージが出るとmod_proxy_balancerは該当のバックエンドにしばらく接続を割り振らなくなる。
以下のごとく複数のバックエンドがありretryを3くらいに設定しておけば比較的ダメージは少ないが・・・。

  <Proxy balancer://www.example.com/>
    BalancerMember http://192.168.1.101 loadfactor=10 retry=3
    BalancerMember http://192.168.1.102 loadfactor=10 retry=3
  </Proxy>

とはいえ3秒以内にすべてのバックエンドがエラー状態になったら503エラーを吐くので、ダメージがないとも言い難い。
というわけでいろいろとロードバランサー側の設定を変えてみたり、バックエンドのhttpdの再起動をしてみたりしたが、どうも解決する気配がなかった。

retry=0の罠

Apacheのドキュメントの英語の方を眺めていたらBalancerMenberのretryに0を指定できるようになっていた。
その場合はバックエンドがエラー状態でも間髪入れずにリトライし続けるとのこと。

  <Proxy balancer://www.example.com/>
    BalancerMember http://192.168.1.101 loadfactor=10 retry=0
    BalancerMember http://192.168.1.102 loadfactor=10 retry=0
  </Proxy>

これに設定してみると503は確かに出なくなった。
しかしエラーメッセージが出っぱなしなのはなんだか気持ち悪いなあ、と思い引き続き設定をいじっていたら、この設定の罠に気がついた。

今回のように元気なのにエラー状態と見なされるのでなんとかしたいという場合はこれでいいが、これは実際に1台死んだときに困る。
接続を死んだ方に割り振り続けるので、サイトが停止する。で、検証したら実際停止した。コエー。

そもそもretry=0が導入された経緯も今回のと同じ問題のようなのだが、これは503を出なくする代わりに冗長性を激しく低下させる諸刃の剣だった。
バックエンドが1台しかない場合は1台死んだらいずれにしろ死ぬので有効に使えると言えるが、複数のバックエンドがある場合は危険すぎる設定。

伝家の宝刀 再起動

そんなこんなで原因追及に時間を費やすこと半日以上。
それだけ経ってようやく、何も設定をいじってないのにエラーが出るようになったと言うことは設定に問題があるのではなく、別に問題があると思い至る。

切り分け能力低さにしばし凹むばかり。なんとも。

ともあれアクセスの少ない時間帯を見計らって、バックエンドの2台を順番に再起動してみることにした。
それで復旧しない場合はロードバランサーの再起動も視野に入れつつ。

結果バックエンドの再起動だけで何事もなかったかのように復旧。
ほぼ1日様子を見たがエラーは皆無。YES!

どうもプロセスがあふれたときにバックエンド側が何か不安定になってしまっていた模様だ。ネットワーク周りかな?
インフラ本職の人ならその原因まで鮮やかに突き止めてしまうのかもしれないが、とりあえず今回は初回の現象だしトリガーになった出来事もつかめているので追わないことにする。

とまあ、もうどうにも困ったときには再起動が効くわけですよ。効くかもしれないのですよ。
ただし再起動を経緯に復旧への道が閉ざされバッドエンドまっしぐらの場合もあるのでご利用は計画的に。

2台あるバックエンドは最悪どっちかつぶれても平気なので再起動は割と気軽にできたが、ロードバランサーは万一死ぬとサイト死亡なので再起動しなくてすんでよかった。
再起動最強だけど再起動は怖い。

前の記事

Titaniumでユニットテスト

次の記事

Node.jsとJasmineでJavaScriptのBDD環境