1前書き

以前は、Ratpackを使用して高性能でリアクティブなアプリケーションを構築する方法について、/ratpack[表示]を参照してください。

この記事では、Netflix HystrixをRatpackアプリケーションと統合する方法について説明します。

Netflix Hystrixは、カスケード障害を防ぐためにアクセスポイントを隔離し、フォールトトレランスのためのフォールバックオプションを提供することによって、分散サービス間の相互作用の制御を支援します。それは私たちがより回復力のあるアプリケーションを構築するのを助けることができます。クイックレビューについては、/Introduction-to-hystrix[Hystrixの紹介]を参照してください。

それで、それが私たちがそれを使う方法です – 私たちはHystrixによってこれらの便利な機能で私たちのRatpackアプリケーションを強化するつもりです。


2 Mavenの依存関係

RatpackでHystrixを使うには、

pom.xml

プロジェクトでratpack-hystrix依存関係が必要です。

<dependency>
    <groupId>io.ratpack</groupId>
    <artifactId>ratpack-hystrix</artifactId>
    <version>1.4.6</version>
</dependency>

ratpack-hystrixの最新版はhttps://search.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22ratpack-hystrix%22%20AND%20g%3A%22io.ratpack%22にあります。[ここに]。

ratpack-hystrixにはhttps://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22io.ratpack%22%20AND%20a%3A%22ratpack-core%22[ratpack-core]が含まれています。

hystrix-core

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

<dependency>
    <groupId>io.ratpack</groupId>
    <artifactId>ratpack-rx</artifactId>
    <version>1.4.6</version>
</dependency>

ratpack-rxの最新版はhttps://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22io.ratpack%22%20AND%20a%3A%22ratpack-rx%22にあります[ここに]。


3 Hystrix Command

を使ってサービングする

Hystrixを使うとき、基になるサービスは通常https://netflix.github.io/Hystrix/javadoc/com/netflix/hystrix/HystrixCommand.html[

HystrixCommand

]またはhttps://netflix.github.io/Hystrix/javadocでラップされています/com/netflix/hystrix/HystrixObservableCommand.html[

HystrixObservableCommand

]。

Hystrixは同期的、非同期的そして事後的な方法でこれらのコマンドの実行をサポートします。これらのうち、反応的なものだけが非閉塞性で公式に推奨されています。

  • 以下の例では、https://developer.github.com/v3/[Github REST API]からプロファイルを取得するエンドポイントをいくつか構築します。


3.1. 反応的コマンド実行

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

public class HystrixReactiveHttpCommand extends HystrixObservableCommand<String> {

   //...

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

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

ここではRatpackのリアクティブhttps://ratpack.io/manual/current/api/index.html?ratpack/http/client/HttpClient.html[

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.baeldung.com"));
}


3.2. 非同期コマンド実行


HystrixCommand

の非同期実行は、スレッドプール上のコマンドをキューに入れ、

Future

を返します。

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


HystrixAsyncHttpCommand

は次のようになります。

public class HystrixAsyncHttpCommand extends HystrixCommand<String> {

   //...

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

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

}

ここでは、Hystrixに制御させたいので非ブロッキングの代わりにブロッキングhttps://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/HttpClient.html[

HttpClient

]を使用します

Future

から応答を受け取るときに自分自身でそれを処理する必要がないように、実際のコマンドの実行タイムアウト。これはまたHystrixが私達の要求を代替するかキャッシュすることを可能にします。

非同期実行でも予想される結果が得られます。

@Test
public void whenFetchAsync__thenGotEugenProfile() {
    assertThat(appUnderTest.getHttpClient().getText("async"),
      containsString("www.baeldung.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.baeldung.com"));
}

4.メトリクス

リンクを登録することで:/ratpack-google-guice[Guiceモジュール] –


HystrixModule


をRatpackレジストリに登録して、リクエストのスコープをストリーミングできます。そして、

GET

エンドポイントを介してイベントストリームを公開します。

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



HystrixMetricsEventStreamHandler


は、https://のメトリックを監視できるように、

text/event-stream

形式でHystrixメトリックをストリーミングするのに役立ちますgithub.com/Netflix-Skunkworks/hystrix-dashboard[

Hystrix Dashboard

]。


standalone Hystrix dashboard

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

リンク:/uploads/Snip20170815__1.png%20775w[]

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


4.1. フードの下


HystrixModule

では、http://netflix.github.io/Hystrix/javadoc/com/netflix/hystrix/strategy/concurrency/HystrixConcurrencyStrategy.html[Hystrix Concurrency Strategy]がhttps://github.com/Netflixを介してHystrixに登録されています。/Hystrix/wiki/Plugins[HystrixPlugin]はRatpackレジストリでリクエストコンテキストを管理します。これにより、各リクエストが始まる前にHystrixリクエストコンテキストを初期化する必要がなくなります。

public class HystrixModule extends ConfigurableModule<HystrixModule.Config> {

   //...

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

   //...

}


5結論

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

いつものように、完全な実装はhttps://github.com/eugenp/tutorials/tree/master/ratpack[the Github project]にあります。