Hystrixを使ったラットパック

Hystrixを備えたラットパック

1. 前書き

以前は、Ratpackを使用して高性能でリアクティブなアプリケーションを構築する方法がshownありました。

この記事では、NetflixHystrixをRatpackアプリケーションと統合する方法を見ていきます。

Netflix Hystrixは、アクセスポイントを分離して連鎖障害を停止し、フォールトトレランスのフォールバックオプションを提供することにより、分散サービス間の相互作用を制御するのに役立ちます。 より回復力のあるアプリケーションを構築するのに役立ちます。 簡単なレビューについては、introduction to Hystrixを参照してください。

そして、それが私たちの使い方です。Hystrixが提供するこれらの便利な機能でRatpackアプリケーションを強化します。

2. メーベン依存

RatpackでHystrixを使用するには、プロジェクトpom.xmlにratpack-hystrix依存関係が必要です。


    io.ratpack
    ratpack-hystrix
    1.4.6

ratpack-hystrixの最新バージョンはhereにあります。 ratpack-hystrixには、ratpack-corehystrix-coreが含まれています。

Ratpackのリアクティブ機能を使用するには、ratpack-rxも必要です。


    io.ratpack
    ratpack-rx
    1.4.6

ratpack-rxの最新バージョンはhereにあります。

3. Hystrixコマンドで提供

Hystrixを使用する場合、基盤となるサービスは通常、HystrixCommandまたはHystrixObservableCommandでラップされます。 Hystrixは、同期、非同期、リアクティブの方法でこれらのコマンドを実行することをサポートしています。 これらのうち、リアクティブのみがノンブロッキングであり、公式に推奨されています。

次の例では、Github REST APIからプロファイルをフェッチするエンドポイントをいくつか作成します。

3.1. リアクティブコマンドの実行

まず、Hystrixを使用してリアクティブバックエンドサービスを構築しましょう。

public class HystrixReactiveHttpCommand extends HystrixObservableCommand {

    //...

    @Override
    protected Observable construct() {
        return RxRatpack.observe(httpClient
          .get(uri, r -> r.headers(h -> h.add("User-Agent", "example HttpClient")))
          .map(res -> res.getBody().getText()));
    }

    @Override
    protected Observable resumeWithFallback() {
        return Observable.just("eugenp's reactive fallback profile");
    }
}

ここでは、RatpackリアクティブHttpClientを使用してGETリクエストを作成します。 HystrixReactiveHttpCommandは、リアクティブハンドラーとして実行できます。

chain.get("rx", ctx ->
  new HystrixReactiveHttpCommand(
    ctx.get(HttpClient.class), eugenGithubProfileUri, timeout)
    .toObservable()
    .subscribe(ctx::render));

エンドポイントは、次のテストで検証できます。

@Test
public void whenFetchReactive_thenGotEugenProfile() {
    assertThat(appUnderTest.getHttpClient().getText("rx"),
      containsString("www.example.com"));
}

3.2. 非同期コマンド実行

HystrixCommandの非同期実行は、スレッドプールでコマンドをキューに入れ、Futureを返します。

chain.get("async", ctx -> ctx.render(
  new HystrixAsyncHttpCommand(eugenGithubProfileUri, timeout)
    .queue()
    .get()));

HystrixAsyncHttpCommandは次のようになります。

public class HystrixAsyncHttpCommand extends HystrixCommand {

    //...

    @Override
    protected String run() throws Exception {
        return EntityUtils.toString(HttpClientBuilder.create()
          .setDefaultRequestConfig(requestConfig)
          .setDefaultHeaders(Collections.singleton(
            new BasicHeader("User-Agent", "example Blocking HttpClient")))
          .build().execute(new HttpGet(uri)).getEntity());
    }

    @Override
    protected String getFallback() {
        return "eugenp's async fallback profile";
    }

}

ここでは、Hystrixに実際のコマンドの実行タイムアウトを制御させて、%(t1からの応答を取得するときに自分で処理する必要がないようにするため、非ブロッキングではなくブロッキングHttpClientを使用します。 )s。 これにより、Hystrixはリクエストをフォールバックまたはキャッシュすることもできます。

非同期実行では、期待される結果も得られます。

@Test
public void whenFetchAsync_thenGotEugenProfile() {
    assertThat(appUnderTest.getHttpClient().getText("async"),
      containsString("www.example.com"));
}

3.3. 同期コマンド実行

同期実行は、現在のスレッドでコマンドを直接実行します。

chain.get("sync", ctx -> ctx.render(
  new HystrixSyncHttpCommand(eugenGithubProfileUri, timeout).execute()));

HystrixSyncHttpCommandの実装は、異なるフォールバック結果を与えることを除いて、HystrixAsyncHttpCommandとほとんど同じです。 フォールバックしない場合、リアクティブおよび非同期実行とまったく同じように動作します。

@Test
public void whenFetchSync_thenGotEugenProfile() {
    assertThat(appUnderTest.getHttpClient().getText("sync"),
      containsString("www.example.com"));
}

4. 測定基準

Guice moduleHystrixModuleをRatpackレジストリに登録することで、リクエストスコープのメトリックをストリーミングし、GETエンドポイントを介してイベントストリームを公開できます。

serverSpec.registry(
  Guice.registry(spec -> spec.module(new HystrixModule().sse())))
  .handlers(c -> c.get("hystrix", new HystrixMetricsEventStreamHandler()));

HystrixMetricsEventStreamHandlerは、Hystrixメトリックをtext/event-stream形式でストリーミングするのに役立ち、Hystrix Dashboardのメトリックを監視できます。

standalone Hystrix dashboardを設定し、Hystrixイベントストリームをモニターリストに追加して、Ratpackアプリケーションのパフォーマンスを確認できます。

image

Ratpackアプリケーションへのいくつかのリクエストの後、ダッシュボードにHystrix関連のコマンドが表示されます。

4.1. フードの下

HystrixModuleでは、Hystrix Concurrency StrategyHystrixPluginを介してHystrixに登録され、Ratpackレジストリでリクエストコンテキストを管理します。 これにより、各リクエストを開始する前にHystrixリクエストコンテキストを初期化する必要がなくなります。

public class HystrixModule extends ConfigurableModule {

    //...

    @Override
    protected void configure() {
      try {
        HystrixPlugins.getInstance().registerConcurrencyStrategy(
          new HystrixRegistryBackedConcurrencyStrategy());
      } catch (IllegalStateException e) {
        //...
      }
    }

    //...

}

5. 結論

この簡単な記事では、HystrixをRatpackに統合する方法と、RatpackアプリケーションのメトリックをHystrixダッシュボードにプッシュしてアプリケーションのパフォーマンスをよりよく表示する方法を示しました。

いつものように、完全な実装はthe Github projectにあります。