LINEエンジニアのonoです。この記事では、LINEのサーバで実際に導入を始めているCircuit Breakerという仕組みについてご紹介します。 Circuit Breakerとは? LINEをはじめとする昨今のWebやアプリのバックエンドサーバシステムは、お互いにAPIやRPCで接続された多数のサービスのネットワークとして構成されるようになってきました。 もしこのネットワークの中の1つが突然全く応答を返さなくなったらどうなるでしょうか? ダウンしたサービスに対するアクセスがタイムアウトするまでブロックすることにより、依存するサービスまでもが連鎖的にダウンしてしまう可能性があります。 もしネットワークの全容を誰も把握できていなかったら、根本の原因がどのサービスにあるのか発見するのに時間がかかってしまうでしょう。 我々はこのような障害の連鎖を防がなくてはいけません。少なくとも、最も重要な機能が影響を受けないようにする必要があります。 そのためには、障害がおきたサービスへのアクセスを遮断しなければなりません。 この仕組みを自動化したものが、Circuit Breakerです。 http://martinfowler.com/bliki/CircuitBreaker.html 上のMartin Fowler氏の記事が詳しいですが、ここで簡単に説明します。 Circuit Breakerとは、リモートアクセスの成功/失敗をカウントし、 エラー率(failure rate)が閾値を超えたときに自動的にアクセスを遮断する仕組みです。 Circuit Breakerはステートマシンとして表現できます。 アクセス成功や失敗といったイベントが発生するたびに内部状態を更新し、障害の検出と復旧の判断を自動的に行います。 それぞれの状態と遷移の条件は以下の通りです。 CLOSED 初期状態です。全てのアクセスは普通に実行されます。 OPEN エラー率が閾値を超えるとOPEN状態になります。全てのアクセスは遮断(fail fast)されます。 HALF_OPEN OPENから一定時間たつとHALF_OPEN状態になります。アクセスを試行し、成功するとCLOSED、失敗するとOPENに戻ります。 Circuit Breaker for Armeria ArmeriaはLINEがオープンソースとして公開している、Nettyベースの非同期Thriftクライアント/サーバライブラリです。Armeriaの素晴らしいところは、decoratorによって機能を簡単に拡張できる点です。 そしてArmeria 0.13.0より、Circuit Breakerをdecoratorとして追加できるようになりました。 Circuit Breakerを使ったThrift Clientの初期化は次のようになります。 Iface helloClient = new ClientBuilder("tbinary+http://127.0.0.1:8080/hello") .decorator( CircuitBreakerClient.newDecorator( new CircuitBreakerBuilder("hello").build() ) ) .build(Iface.class); 簡単ですね。 そして、このThrift Clientを呼び出すコードは次のようになります。 try { helloClient.hello("line"); } catch (TException e) { // error handling } catch (FailFastException e) { // fallback code } Circuit Breakerが障害を検知すると、Thrift ClientはFailFastExceptionを投げるので、適切なフォールバックコードを実行します。 非同期Clientの場合も同様です。 helloClient.hello("line", new AsyncMethodCallback() { public void onComplete(Object response) { // response handling } public void onError(Exception e) { if (e instanceof TException) { // error handling } else if (e (…)
↧