著者:Joe McClur
このブログでは、マイクロサービスを使用するアプリケーションのスループットを最適化したベストプラクティスをご紹介します。特に、サービス間通信と JSON 処理のに焦点を当てています。
サービス間の通信
マイクロサービスでは、サービス間で RESTful APIを実行することが多いですが、これがパフォーマンスのボトルネックになる可能性があります。 呼び出しを行うクライアントが正しく構成されていることを確認する必要があります。
例 1: MicroProfile Rest クライアント
MicroProfile Rest クライアントにおけるベスト・プラクティスは単に @ApplicationScopedを作成することです。 デフォルトでは、 MicroProfileの Rest クライアントのスコープは@Dependentです。これを例えばJakarta RESTfulエンドポイントに注入すると、 Jakarta RESTful クラスのスコープ(デフォルトは @RequestScoped)を継承します。
このようにデフォルトのスコープを使うと、毎回新しい MicroProfile Rest クライアントが作成されてしまって、 その都度CPU コストがかかり、クラスの読み込みのオーバーヘッドが大きくなって処理速度が低下します。MicroProfile Rest クライアントを@ApplicationScopedで作成すれば、クライアントは一度だけ作成され、コストを節約することができます。
* 注: Jakartaの RESTful クラスの実際のデフォルト・スコープは、少々分かりづらいのですが、 @RequestScoped と同等のものと考えられるでしょう。読者のみなさんのマイクロサービス・アプリケーションがステートレスであることを考えると、Jakartaの RESTfulクラスを @ApplicationScopedで作ることもパフォーマンス向上の効果があると思います。
上記の説明では、分かりづらいかもしれないので、もう少しはっきりした具体例を下記にご紹介します。
この例では、 Apache JMeterから 、server1上のアプリケーション ( 下記のクライアントのコードがあるアプリケーション ) にリクエストを送って、負荷をかけます。 このアプリケーションは、 server2でホストされている別のマイクロサービスを呼び出します。
ケース 1 - デフォルトのスコープを使う場合
ここでは、 MicroProfile Rest クライアントを注入し、 server1 から server2への呼び出しを行う REST エンドポイントのコードを示します。
@Path("/mp-restclient-test1")
public class MicroProfileRestClientTest1 {
@Inject @RestClient
private DefaultRestClient defaultClient;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String ping() throws Exception {
String returnString = defaultClient.ping();
defaultClient.close();
return returnString;
}
}
以下に、 MicroProfile Rest クライアント・インターフェースを示します。
@Path("/")
@RegisterRestClient(configKey="defaultRestClient")
public interface DefaultRestClient extends AutoCloseable {
@GET
@Path("/endpoint")
@Produces(MediaType.TEXT_PLAIN)
public String ping();
}
ケース 2 – ApplicationScopedを使う場合
この場合、 REST エンドポイントは類似していますが、すべての呼び出し後にクライアントをクローズする必要がありません、というのもスコープの範囲外になることがないからです。
@Path("/mp-restclient-test2")
public class MicroProfileRestClientTest2 {
@Inject @RestClient
private AppScopedRestClient appScopedClient;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String ping() {
return appScopedClient.ping();
}
}