この記事では、Azure Spring Cloud Enterprise で VMware Tanzu® Service Registry を使用する方法について説明します。
Tanzu Service Registry は、商用 VMware Tanzu コンポーネントの 1 つです。 これにより、マイクロサービス・アーキテクチャの主要な考え方の 1 つである Service Discovery パターンを適用したアプリケーションの開発がとても簡単になります。 各サービスのクライアントを、手動で構成したり、特定の形式のアクセス規則を適用することは困難で、特に本番環境においては不安になります。 その代わりに Tanzu Service Registry を使用すると、登録済みのサービスをアプリケーションで動的に検出し、呼び出すことができます。
通常、Spring Boot のアプリケーションで、Service Registry や Discovery の機能を利用するためには、通常、Service Registration and Discovery に記載されているよう手順で行います。
基本的には、Eureka Service Registry のサーバを自身で作成して起動し、起動した後 Eureka Client からサーバに接続を行います。 この際クライアントから Eureka Server にアクセスする事で登録されている Eureka Client の情報を取得しアクセスすることになります。
Azure Spring Cloud を利用すると、自分自身で Eureka Server (Service Registry) のサービスを作成したり起動しなくてもよく、Azure Spring Cloud Enterprise の作成時に Service Registry にチェックする事で簡単に利用できるようになります。
前提条件
事前に、Tanzu Service Registry を有効化して Azure Spring Cloud Enterprise をプロビジョニングしておいてください。
詳細については、「Quickstart: Provision an Azure Spring Cloud service instance using the Enterprise tier」を参照してください。
[!NOTE]
Tanzu Service Registry を使用するためには、Azure Spring Cloud サービス インスタンスをプロビジョニングする際に有効にする必要があります。 現在は、プロビジョニング後に有効化することはできません。
以降の説明時では、Azure Spring Cloud Enterprise の作成時に使用したリソース・グループ名、インスタンス名をそれぞれ下記に定義します。ご自身の作成した環境に合わせて適宜変数の内容を書き換えてご利用ください。
項目 | 変数名 |
---|---|
リソース・グループ名 | $RESOURCE-GROUP |
インスタンス名 | $AZURE_SPRING_CLOUD_NAME |
How to Guide の進め方
本ガイドでは、Azure Spring Cloud の Service Registry に対してサービスを登録する方法、そして別サービスから参照する方法を下記に従い説明していきます。
- Service A を作成し基本的な実装方法について紹介します
- 作成した Service A を Azure Spring Cloud にデプロイし、Service Registry に登録します
- 別の Service B を作成し Service A を呼び出すように実装します
- Service B をデプロイし、Service Registry に登録します
- Service B を通じて Service A を呼び出します
Service Registry を利用したアプリケーションの作成
1. Spring Boot でサービス A を実装
コチラの 「Create Sample Service A」 のリンクを押下してください。すると下記のような画面が表示されます。
ここで、GENERATE
ボタンを押すと、下記のような Spring Boot のサンプル・プロジェクをが入手できます。
.
├── HELP.md
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── foo
│ │ └── bar
│ │ └── Sample
│ │ └── Service
│ │ └── A
│ │ └── SampleServiceAApplication.java
│ └── resources
│ ├── application.properties
│ ├── static
│ └── templates
└── test
└── java
└── foo
└── bar
└── Sample
└── Service
└── A
└── SampleServiceAApplicationTests.java
1.1 Service Registry Client (Eureka Client) の依存ライブラリの設定を確認
Spring Cloud Service Registry を使用して Service Registry と Discovery を管理できるようにするには、アプリケーションの pom.xml
ファイルに依存関係を追加する必要があります。 spring-cloud-starter-netflix-eureka-client
の依存関係が pom.xml に含まれている事を確認してください。追加されていない場合は、依存関係を追加してください。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
1.2 Eureka Client として実装
SampleServiceAApplication.java
に対して @EnableEurekaClient
アノテーションを追加し Eureka Client として作成します。
package foo.bar.Sample.Service.A;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class SampleServiceAApplication {
public static void main(String[] args) {
SpringApplication.run(SampleServiceAApplication.class, args);
}
}
この設定だけで、この Spring Boot のサービスは Eureka Client として動作するようになります。
1.3 テスト用 REST Endpoint の作成
上記で、Service Registry にサービスを登録する事はできますが、実際のサービスが何も実装されていなければ検証ができません。そこで、他の外部サービスから呼び出しができるように、簡単な RESTful エンドポイントを一つ作成します。下記のコードを実装してください。
package foo.bar.Sample.Service.A;
import java.util.Map;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ServiceAEndpoint {
@GetMapping("/serviceA")
public String getServiceA(){
return "This is a result of Service A";
}
@GetMapping("/env")
public Map<String, String> getEnv(){
Map<String, String> env = System.getenv();
return env;
}
}
1.4 Spring Boot アプリケーションのビルドと動作確認
以上で、簡単なサービスが出来ましたので、ソースコードをコンパイルしビルドしてください。下記の mvn
コマンドを実行してください。
mvn clean package
2. サービス A をデプロイし Service Registry に登録
次に、上記で作成したサービス A を Azure Spring Cloud Enterprise にデプロイし Service Registry に登録する方法について紹介します。
2.1 Azure Spring Cloud アプリケーションの作成
まず、Azure Spring Cloud にアプリケーションを作成します。
アプリケーションを作成するためには、az spring-cloud app create
コマンドを使用します。
今回は、検証用に --assign-endpoint
を指定しパブリック IP を付与しています。これにより、外部ネットワークからのアクセスが可能になります。
az spring-cloud app create \
-g $RESOURCE-GROUP \
-s $AZURE_SPRING_CLOUD_NAME \
--name serviceA \
--instance-count 1 \
--memory 2Gi \
--assign-endpoint
2.2 Service Registry への接続方法について (バインドについて)
ここまでで Spring Boot でサービスを作成し、Azure Spring Cloud にアプリケーション作成しました。
これから、アプリケーションをデプロイして動作確認を行ってまいりますが、Service Registry を利用するために一つやらなければならない事があります。それは、Service Registry に対してアプリケーションをバインドし、Service Registry への接続情報を取得できるようにすることです。
通常、Eureka Client の実装では、Spring Boot アプリケーションの application.properties
設定ファイルに、下記のような接続情報の設定を記述し、サーバと接続できるようにします。
eureka.client.service-url.defaultZone=http://eureka:8761/eureka/
しかし上記の設定をアプリケーション内に直接記述した場合、Service Registry のサーバが変わるたびに、再編集し再度プロジェクトをビルドする必要があります。こうした手間を防ぐために、Azure Spring Cloud では Service Registry を参照するために、「Service Registry にアプリケーションをバインド」 する方法で、Service Registry への接続情報を取得できるようにしています。
具体的には、Service Registry にアプリケーションをバインドする事で、Service Registry の接続情報(eureka.client.service-url.defaultZone
) を Java の環境変数にを追加します。これにより、アプリケーションの起動時に環境変数の内容を読み込む事で Service Registry に接続ができるようになります。
実際には、JAVA_TOOL_OPTIONS に対して、下記の環境変数が追加されます。
-Deureka.client.service-url.defaultZone=https://$AZURE_SPRING_CLOUD_NAME.svc.azuremicroservices.io/eureka/default/eureka
2.3 Service Registry にサービスをバインド
Azure Service Registry にサービスをバインドするために、az spring-cloud service-registry bind
コマンドを実行してください。これにより、アプリケーションを Service Registry にバインドし、サーバに接続できるようになります。
az spring-cloud service-registry bind \
-g $RESOURCE-GROUP \
-s $AZURE_SPRING_CLOUD_NAME \
--app serviceA
アプリケーションのバインドは、Azure Portal からも設定できます。
[!NOTE]
Service Registry に対する変更が、全てのアプリケーションに伝搬するためには数分かかります。
[!NOTE]
アプリケーションにおいて、バインド/アンバインドのステータスを変更する場合、アプリケーションを再起動、もしくは再デプロイする必要があります。
2.4 Azure Spring Cloud にアプリケーションのデプロイ
アプリケーションをバインドしたので、次に、Spring Boot の成果物ファイル (Sample-Service-A-0.0.1-SNAPSHOT.jar
) を、Azure Spring Cloud 上にデプロイをします。デプロイするためには、下記の az spring-cloud app deploy
コマンドを実行してください。
az spring-cloud app deploy \
-g $RESOURCE-GROUP \
-s $AZURE_SPRING_CLOUD_NAME \
--name serviceA \
--artifact-path ./target/Sample-Service-A-0.0.1-SNAPSHOT.jar \
--jvm-options="-Xms1024m -Xmx1024m"
デプロイが成功しているかを確認するため、下記の az spring-cloud app list
コマンドを実行してください
az spring-cloud app list \
-g $RESOURCE-GROUP \
-s $AZURE_SPRING_CLOUD_NAME \
-o table
実行すると下記のような結果が表示されます。
Name Location ResourceGroup Public Url Production Deployment Provisioning State CPU Memory Running Instance Registered Instance Persistent Storage Bind Service Registry Bind Application Configuration Service
------------------------ ------------- ---------------------- ------------------------------------------------------------------- ----------------------- -------------------- ----- -------- ------------------ --------------------- -------------------- ----------------------- ----------------------------------------
servicea southeastasia $RESOURCE-GROUP https://$AZURE_SPRING_CLOUD_NAME-servicea.azuremicroservices.io default Succeeded 1 2Gi 1/1 N/A - - -
2.5 サービス A アプリケーションの動作確認
上記コマンドの実行結果より、Public Url
に記載されている URL に、実装した RESTful エンドポイント(/serviceA
) を付け加えてアクセスしてください。成功すると下記のような文字列が返ってきます。
curl https://AZURE_SPRING_CLOUD_NAME-servicea.azuremicroservices.io/serviceA
This is a result of Service A
サービス A では、環境変数の一覧を表示する RESTful エンドポイントも作成しました。環境変数を確認するために、エンドポイント (/env
) にアクセスしてください。
すると環境変数の一覧が表示されます。
curl https://$AZURE_SPRING_CLOUD_NAME-servicea.azuremicroservices.io/env
表示された結果を確認すると、Java の起動オプションに (JAVA_TOOL_OPTIONS
)、eureka.client.service-url.defaultZone
が追加されている事を確認できます。これにより、アプリケーションは Service Registry にサービスを登録し、他のサービスから利用できるようになります。
"JAVA_TOOL_OPTIONS":"-Deureka.client.service-url.defaultZone=https://$AZURE_SPRING_CLOUD_NAME.svc.azuremicroservices.io/eureka/default/eureka
以上で、サービスを Azure Spring Cloud の Service Registry (Eureka Server) に登録できました。これで他のサービスから、Service Registry を使用して該当サービスにアクセスできるようになります。
3. サービス B から Service Registry 経由でサービス A にアクセスするプログラムの実装
3.1 Spring Boot でサービス B を実装
1.1 と同様、コチラの 「Create Sample Service B」 のリンクから GENERATE
ボタンを押下し、新しいサービス B のプロジェクトを作成してください。
3.2 サービス B を Eureka Client として実装
Service A と同様に Service B も @EnableEurekaClient
のアノテーションを追加し Eureka Client として実装します。
package foo.bar.Sample.Service.B;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class SampleServiceBApplication {
public static void main(String[] args) {
SpringApplication.run(SampleServiceBApplication.class, args);
}
}
3.3 Service B のエンドポイントを実装
次に、Service A を呼び出すためのエンドポイント (/invoke-serviceA
) を実装します。ここでは、サンプルを簡単にするため RestTemplate
でサービス A を呼び出し、サービス B から呼び出された事がわかるように、文字列 ("INVOKE SERVICE A FROM SERVICE B: "
) を追加して返しています。
また、検証のため /list-all
のエンドポイントも追加しています。これは、サービスが正しく Service Registry と通信を行えているかを確認するために実装しています。このエンドポイントを呼び出すと Service Registry に登録されているアプリケーションの一覧を取得できます。
package foo.bar.Sample.Service.B;
import java.util.List;
import java.util.stream.Collectors;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.shared.Application;
import com.netflix.discovery.shared.Applications;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class ServiceBEndpoint {
@Autowired
private EurekaClient discoveryClient;
@GetMapping(value = "/invoke-serviceA")
public String invokeServiceA()
{
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject("http://servicea/serviceA",String.class);
return "INVOKE SERVICE A FROM SERVICE B: " + response;
}
@GetMapping(value = "/list-all")
public List<String> listsAllServices() {
Applications applications = discoveryClient.getApplications();
List<Application> registeredApplications = applications.getRegisteredApplications();
List<String> appNames = registeredApplications.stream().map(app -> app.getName()).collect(Collectors.toList());
return appNames;
}
}
3.4 Service B のソースコードのビルド
下記のコマンドを実行し、Maven プロジェクトをビルドしてください。
mvn clean package
4. Service B を Azure Spring Cloud にデプロイし、Service Registry に登録
サービス B をデプロイするために、Azure Spring Cloud にアプリケーションを作成してください。
az spring-cloud app create \
-g $RESOURCE-GROUP \
-s $AZURE_SPRING_CLOUD_NAME \
--name serviceB \
--instance-count 1 \
--memory 2Gi \
--assign-endpoint
アプリケーションを作成した後、次に Service Registry にアプリケーションをバインドしてください。
az spring-cloud service-registry bind \
-g $RESOURCE-GROUP \
-s $AZURE_SPRING_CLOUD_NAME \
--app serviceB
バインドが完了したのち、サービスをデプロイしてください。
az spring-cloud app deploy \
-g $RESOURCE-GROUP \
-s $AZURE_SPRING_CLOUD_NAME \
--name serviceB \
--artifact-path ./target/Sample-Service-B-0.0.1-SNAPSHOT.jar \ --jvm-options="-Xms1024m -Xmx1024m"
デプロイが完了した後、アプリケーションの状況を確認してください。
az spring-cloud app list \
-g $RESOURCE-GROUP \
-s $AZURE_SPRING_CLOUD_NAME \
-o table
サービス A, サービス B が正しくデプロイされている場合、下記のような画面が表示されます。
Name Location ResourceGroup Public Url Production Deployment Provisioning State CPU Memory Running Instance Registered Instance Persistent Storage Bind Service Registry Bind Application Configuration Service
-------- ------------- ---------------------- ------------------------------------------------------------ ----------------------- -------------------- ----- -------- ------------------ --------------------- -------------------- ----------------------- ----------------------------------------
servicea southeastasia SpringCloud-Enterprise https://$AZURE_SPRING_CLOUD_NAME-servicea.azuremicroservices.io default Succeeded 1 2Gi 1/1 1/1 - default -
serviceb southeastasia SpringCloud-Enterprise https://$AZURE_SPRING_CLOUD_NAME-serviceb.azuremicroservices.io default Succeeded 1 2Gi 1/1 1/1 - default -
5. Service B から Service A を呼び出す
上記のコマンドの実行結果から、サービス B の URL に対してアクセスします。この時、エンドポイント (/invoke-serviceA
) を追加して実行してください。すると ’INVOKE SERVICE A FROM SERVICE B: This is a result of Service A’ の文字列が返されている事を確認できます。
この実行結果より、サービス B からサービス A を呼び出し、その結果が正しく返ってきている事が確認できました。
curl https://$AZURE_SPRING_CLOUD_NAME-serviceb.azuremicroservices.io/invoke-serviceA
INVOKE SERVICE A FROM SERVICE B: This is a result of Service A
ここで改めて、サービス B の実装ソースコードを確認してみます。
String response = restTemplate.getForObject("http://servicea/serviceA",String.class);
このように、プログラム上 Azure Spring Cloud のアプリケーションを作成する際に指定した名前で、アクセスしています。(例:az spring-cloud app create --name ServiceA
)
アプリケーション名と Service Registry に登録するサービス名が一致しているため、サービス名の管理もやりやすくなります。
5.1 サービス から Service Registry の情報を参照
最後に、/list-all
のエンドポイントにアクセスし、サービスから Service Registry の情報を取得します。ここでは、Service Registry に登録されているサービスの一覧を取得しています。
curl https://$AZURE_SPRING_CLOUD_NAME-serviceb.azuremicroservices.io/list-all
["SERVICEA","EUREKA-SERVER","SERVICEB"]
このように、必要に応じてプログラム上からも細かな情報を取得する事ができるようになっています。