The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

Stork リファレンスガイド

プレビュー

このガイドは、 Stork 入門ガイドと対です。QuarkusでのSmallRye Stork統合の設定と使用方法について説明しています。

この技術は、previewと考えられています。

preview では、下位互換性やエコシステムでの存在は保証されていません。具体的な改善には設定や API の変更が必要になるかもしれませんが、 stable になるための計画は現在進行中です。フィードバックは メーリングリストGitHub の課題管理 で受け付けています。

とりうるステータスの完全なリストについては、 FAQの項目 を参照してください。

対応クライアント

現在のStork統合で対応しているのは次の通りです:

  • リアクティブRESTクライアント

  • gRPCクライアント

注意: gRPCクライアント統合は、統計ベースのロードバランサーをサポートしていません。

利用可能なサービスディスカバリーと選択

提供されるサービスディスカバリーと選択については、 SmallRye Storkのウェブサイトをご確認ください。

KubernetesでのStorkの使用

Storkは、Kubernetesがデフォルトで提供しているものを超える、Kubernetesのサービスディスカバリーサポートを提供します。これは、KubernetesのサービスをバックアップしているすべてのPodを探しますが、Kubernetesのようにラウンドロビンを適用するのではなく、Storkのロードバランサーを使用してポッドを選択するオプションを提供します。

この機能を使用するには、プロジェクトに以下の依存関係を追加します。

pom.xml
<dependency>
    <groupId>io.smallrye.stork</groupId>
    <artifactId>stork-service-discovery-kubernetes</artifactId>
</dependency>
build.gradle
implementation("io.smallrye.stork:stork-service-discovery-kubernetes")

Kubernetes Serviceとして公開される予定の各サービスについて、ルックアップを設定します。

quarkus.stork.my-service.service-discovery.type=kubernetes
quarkus.stork.my-service.service-discovery.k8s-namespace=my-namespace

Storkは、指定された名前(前の例では my-service )のKubernetes Serviceを指定された名前空間で探します。StorkはKubernetes ServiceのIPを直接使用し、選択とバランシングをKubernetesに任せるのではなく、サービスを検査し、サービスを提供しているポッドのリストを取得します。そして、インスタンスを選択することができます。

KubernetesでStorkを使う詳しい例は、 Kubernetes で Stork を使用 をお読みください。

カスタムサービスディスカバリーの実装

Storkは拡張性があり、独自のサービスディスカバリーメカニズムを実装することができます。

依存関係

サービス ディスカバリー プロバイダーを実装するには、プロジェクトが Core と Configuration Generator に依存していることを確認してください。前者はカスタムディスカバリーの実装に必要なクラスを提供し、後者はStorkが必要とするクラスを生成するアノテーションプロセッサを含んでいます。

pom.xml
<dependency>
    <groupId>io.smallrye.stork</groupId>
    <artifactId>stork-core</artifactId>
</dependency>
<dependency>
    <groupId>io.smallrye.stork</groupId>
    <artifactId>stork-configuration-generator</artifactId>
    <!-- provided scope is sufficient for the annotation processor -->
    <scope>provided</scope>
</dependency>
build.gradle
implementation("io.smallrye.stork:stork-core")
compileOnly("io.smallrye.stork:stork-configuration-generator")

プロバイダがエクステンションに配置されている場合、設定ジェネレータは実行時モジュールの annotationProcessorPaths セクションでデフォルトのスコープを使用して宣言する必要があります。

<annotationProcessorPaths>
  ...
  <path>
    <groupId>io.smallrye.stork</groupId>
    <artifactId>stork-configuration-generator</artifactId>
  </path>
</annotationProcessorPaths>

サービスディスカバリープロバイダーの実装

カスタムプロバイダーは、このサービスディスカバリープロバイダーを使用して設定されたサービスごとに io.smallrye.stork.ServiceDiscovery インスタンスを作成するファクトリーです。例えば acme のようなタイプが各プロバイダを識別します。このタイプは、設定でプロバイダーを参照するために使用されます。

quarkus.stork.my-service.service-discovery.type=acme

最初のステップは、 io.smallrye.stork.spi.ServiceDiscoveryProvider インターフェースの実装です。

package examples;

import io.smallrye.stork.api.ServiceDiscovery;
import io.smallrye.stork.api.config.ServiceConfig;
import io.smallrye.stork.api.config.ServiceDiscoveryAttribute;
import io.smallrye.stork.api.config.ServiceDiscoveryType;
import io.smallrye.stork.spi.StorkInfrastructure;
import io.smallrye.stork.spi.ServiceDiscoveryProvider;

@ServiceDiscoveryType("acme") (1)
@ServiceDiscoveryAttribute(name = "host",
        description = "Host name of the service discovery server.", required = true) (2)
@ServiceDiscoveryAttribute(name = "port",
        description = "Port of the service discovery server.", required = false)
public class AcmeServiceDiscoveryProvider (3)
        implements ServiceDiscoveryProvider<AcmeConfiguration> {

    (4)
    @Override
    public ServiceDiscovery createServiceDiscovery(AcmeConfiguration config,
                                                   String serviceName,
                                                   ServiceConfig serviceConfig,
                                                   StorkInfrastructure storkInfrastructure) {
        return new AcmeServiceDiscovery(config);
    }
}

この実装は単純です。

1 @ServiceDiscoveryType アノテーションは、サービスディスカバリープロバイダーのタイプを定義します。このアノテーションでアノテーションされた各 ServiceDiscoveryProvider に対して、設定クラスが生成されます。構成クラスの名前は、プロバイダの名前に Configuration を付加して構成されます。
2 このサービスディスカバリープロバイダーで構成されたサービスの設定プロパティを定義するには、 @ServiceDiscoveryAttribute を使用します。設定プロパティは、フォームのすべてのプロパティから次の形で収集されます: stork.my-service.service-discovery.attr=value.
3 プロバイダは、設定クラスによって型付けされた ServiceDiscoveryType を実装する必要があります。この設定クラスは、Configuration Generatorによって自動的に生成されるます。その名前は、 AcmeConfiguration のように,サービスディスカバリー型に Configuration を付加して作成されます。
4 createServiceDiscovery メソッドは、ファクトリーメソッドです。このメソッドは、設定を受け取り、サービスの名前と利用可能なインフラへのアクセスを行います。

次に、 ServiceDiscovery インターフェースを実装する必要があります。

package examples;

import java.util.Collections;
import java.util.List;

import io.smallrye.mutiny.Uni;
import io.smallrye.stork.api.ServiceDiscovery;
import io.smallrye.stork.api.ServiceInstance;
import io.smallrye.stork.impl.DefaultServiceInstance;
import io.smallrye.stork.utils.ServiceInstanceIds;

public class AcmeServiceDiscovery implements ServiceDiscovery {

    private final String host;
    private final int port;

    public AcmeServiceDiscovery(AcmeConfiguration configuration) {
        this.host = configuration.getHost();
        this.port = Integer.parseInt(configuration.getPort());
    }

    @Override
    public Uni<List<ServiceInstance>> getServiceInstances() {
        // Proceed to the lookup...
        // Here, we just return a DefaultServiceInstance with the configured host and port
        // The last parameter specifies whether the communication with the instance should happen over a secure connection
        DefaultServiceInstance instance =
                new DefaultServiceInstance(ServiceInstanceIds.next(), host, port, false);
        return Uni.createFrom().item(() -> Collections.singletonList(instance));
    }
}

繰り返しになりますが、この実装は単純過ぎるものです。一般的には、設定から得た値でサービス・インスタンスを作成するのではなく、サービス・ディスカバリー・バックエンドに接続してサービスを探し、それに応じてサービス・インスタンスのリストを作成します。これが、このメソッドが Uni を返す理由です。ほとんどの場合、ルックアップはリモート操作で行われます。

サービスディスカバリーの利用

これを使用するプロジェクトでは、実装を提供するモジュールへの依存を忘れずに追加してください。そして、設定では、以下の追加だけが必要です:

quarkus.stork.my-service.service-discovery.type=acme
quarkus.stork.my-service.service-discovery.host=localhost
quarkus.stork.my-service.service-discovery.port=1234

そして、Storkはあなたの実装を使って、 my-service のサービスを探します。

カスタムサービス選択/ロードバランサーの実装

Storkは拡張性があり、独自のサービス選択(ロードバランサー)メカニズムを実装することができます。

依存関係

ロードバランサープロバイダーを実装するには、プロジェクトが Core と Configuration Generator に依存していることを確認してください。前者はカスタムロードバランサーの実装に必要なクラスを提供し、後者はStorkが必要とするクラスを生成するアノテーションプロセッサを含んでいます。

pom.xml
<dependency>
    <groupId>io.smallrye.stork</groupId>
    <artifactId>stork-core</artifactId>
</dependency>
<dependency>
    <groupId>io.smallrye.stork</groupId>
    <artifactId>stork-configuration-generator</artifactId>
    <!-- provided scope is sufficient for the annotation processor -->
    <scope>provided</scope>
</dependency>
build.gradle
implementation("io.smallrye.stork:stork-core")
compileOnly("io.smallrye.stork:stork-configuration-generator")

カスタム ディスカバリー プロバイダと同様に、プロバイダがエクステンションに配置されている場合は、ランタイム モジュールの annotationProcessorPaths セクションでデフォルト スコープを使用して設定ジェネレータを宣言する必要があります。

ロードバランサー・プロバイダーの実装

ロードバランサーの実装は3つの要素で構成されています:

  • LoadBalancer Stork サービスのサービスインスタンスを選択する責任があります。

  • LoadBalancerProvider ロードバランサーの type に応じて LoadBalancer のインスタンスを作成します。

  • ロードバランサーの設定である LoadBalancerProviderConfiguration

type は、例えば acme のように、各プロバイダーを識別します。この type は、設定でプロバイダーを参照するために使用されます。

quarkus.stork.my-service.load-balancer.type=acme

ServiceDiscoveryProvider と同様に、 LoadBalancerProvider の実装は type を定義する @LoadBalancerType のアノテーションが必要です。プロバイダーが期待する設定プロパティは、プロバイダーに置かれた @LoadBalancerAttribute のアノテーションで定義する必要があります。

package examples;

import io.smallrye.stork.api.LoadBalancer;
import io.smallrye.stork.api.ServiceDiscovery;
import io.smallrye.stork.api.config.LoadBalancerAttribute;
import io.smallrye.stork.api.config.LoadBalancerType;
import io.smallrye.stork.spi.LoadBalancerProvider;

@LoadBalancerType("acme")
@LoadBalancerAttribute(name = "my-attribute",
        description = "Attribute that alters the behavior of the LoadBalancer")
public class AcmeLoadBalancerProvider implements
        LoadBalancerProvider<AcmeLoadBalancerProviderConfiguration> {

    @Override
    public LoadBalancer createLoadBalancer(AcmeLoadBalancerProviderConfiguration config,
                                           ServiceDiscovery serviceDiscovery) {
        return new AcmeLoadBalancer(config);
    }
}

なお、 ServiceDiscoveryProvider と同様に、 LoadBalancerProvider インターフェースもパラメータとして設定クラスを受け取ります。この設定クラスは、 Configuration Generator によって自動的に生成されます。その名前は、プロバイダークラスの名前に Configuration を付加して作成されます。

次のステップは、 LoadBalancer インターフェースを実装することです。

package examples;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Random;

import io.smallrye.stork.api.LoadBalancer;
import io.smallrye.stork.api.NoServiceInstanceFoundException;
import io.smallrye.stork.api.ServiceInstance;

public class AcmeLoadBalancer implements LoadBalancer {

    private final Random random;

    public AcmeLoadBalancer(AcmeLoadBalancerProviderConfiguration config) {
        random = new Random();
    }

    @Override
    public ServiceInstance selectServiceInstance(Collection<ServiceInstance> serviceInstances) {
        if (serviceInstances.isEmpty()) {
            throw new NoServiceInstanceFoundException("No services found.");
        }
        int index = random.nextInt(serviceInstances.size());
        return new ArrayList<>(serviceInstances).get(index);
    }
}

繰り返しになりますが、この実装は単純過ぎるもので、受信したリストからランダムにインスタンスを選択するだけです。

examples.AcmeLoadBalancerProvider

ロードバランサーの使用

これを使用するプロジェクトでは、実装を提供するモジュールへの依存を忘れずに追加してください。そして、設定では、以下の追加だけが必要です:

quarkus.stork.my-service.service-discovery.type=...
quarkus.stork.my-service.load-balancer.type=acme

その後、Storkはあなたの実装を使って my-service のサービスインスタンスを選択します。