原文はこちら。
https://community.oracle.com/community/cloud_computing/oracle-cloud-developer-solutions/blog/2017/04/04/dynamic-load-balancing-for-docker-based-javaee-microservices-on-oracle-container-cloud
このエントリではDockerベースのJava EEマイクロサービスをHAProxyを使ってHA/負荷分散モードで実行する方法をご紹介します。全てOracle Container Cloud上で実行します。
以下のコマンドを実行します。
これは、Oracle Container Cloudサービス・レジストリ内のキーに関する情報をHAProxyサービスに提供します。このレジストリを使って(前述の)confdサービスが実際に新しいアプリケーション・インスタンスを自動検出します。8080は公開されたポート番号ですが、これ自体がサービスレジストリのキーの一部でもあるため、ハードコードされています。
StacksメニューからNew Stackを選択してプロセスを開始します。
Advanced EditorをクリックしてYAMLコンテンツを入力します。
これで個々のサービスが見えるはずです。Stack Nameを指定して[Save]をクリックします。
Stacksメニューに戻って、新規作成されたStackを[Deploy]をクリックしてデプロイします。
ロードバランシングをテストするため、rest-api(バックエンド)サービスの3個のインスタンスをデプロイし、1個の負荷分散(HAProxy)サービスと紐付けます。
数秒後、全てのコンテナが実行中状態になっていることを確認できるはずです。今回は、この3個のサービスと1個のha-proxyロードバランサのインスタンスが実行中になっています。
Service Discoveryメニューをチェックして書くインスタンスが存在することを確認しましょう。前述の通り、これはconfdサービスがアプリケーションの新規インスタンスを自動検出することでイントロスペクトされています(自動的にこのレジストリに追加されます)。
以下のcURLコマンドを実行して確認しましょう。
少々したら、追加されたアプリケーション・インスタンス(5個目のインスタンス)が確認できることでしょう。コマンドを再度実行し、負荷分散が想定通り動作していることを確認しましょう。
https://community.oracle.com/community/cloud_computing/oracle-cloud-developer-solutions/blog/2017/04/04/dynamic-load-balancing-for-docker-based-javaee-microservices-on-oracle-container-cloud
このエントリではDockerベースのJava EEマイクロサービスをHAProxyを使ってHA/負荷分散モードで実行する方法をご紹介します。全てOracle Container Cloud上で実行します。
HAProxy - The Reliable, High Performance TCP/HTTP Load Balancer簡単に概要をご紹介します。
http://www.haproxy.org/
Oracle Container Cloud Service
https://cloud.oracle.com/ja_JP/container
- WildFly Swarmを使うJava EEマイクロサービス
シンプルなJAX-RSベースのRESTアプリケーション - HAProxy
アプリケーションの複数インスタンスへの負荷分散に利用 - Docker
個々のコンポーネント、つまりマイクロサービスおよび負荷分散サービスをDockerイメージにパッケージング - Oracle Container Cloud
Oracle Container Cloud上でサービスを構成し、スケーラブルかつ負荷分散しながらサービスを実行します。
Application
このアプリケーションは、株価を取得する非常にシンプルなJAX-RSを使うREST APIです。WildFly Swarmは単なるJava EEランタイムとして利用しています。シンプルなWARベースのJava EEプロジェクトを作成し、Swarm Mavenプラグインを使って、必要なパーツを自動的に検出して構成し、WARからfat JARを作成するという、"魔法"を織り込みます。@GET
public String getQuote(@QueryParam("ticker") final String ticker) {
Response response = ClientBuilder.newClient().
target("https://www.google.com/finance/info?q=NASDAQ:" + ticker).
request().get();
if (response.getStatus() != 200) {
//throw new WebApplicationException(Response.Status.NOT_FOUND);
return String.format("Could not find price for ticker %s", ticker);
}
String tick = response.readEntity(String.class);
tick = tick.replace("// [", "");
tick = tick.replace("]", "");
return StockDataParser.parse(tick)+ " from "+ System.getenv("OCCS_CONTAINER_NAME");
}
WildFly Swarm
http://wildfly-swarm.io/
<build>
<finalName>occ-haproxy</finalName>
<plugins>
<plugin>
<groupId>org.wildfly.swarm</groupId>
<artifactId>wildfly-swarm-plugin</artifactId>
<version>1.0.0.Final</version>
<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<compilerArguments>
<endorseddirs>${endorsed.dir}</endorseddirs>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<outputDirectory>${endorsed.dir}</outputDirectory>
<silent>true</silent>
<artifactItems>
<artifactItem>
<groupId>javax</groupId>
<artifactId>javaee-endorsed-api</artifactId>
<version>7.0</version>
<type>jar</type>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
WildFly Swarmの代わりに、別のJava EEベースのfat JARスタイルのフレームワーク、例えばPayara MicroやKumuluzEE、Apache TomEE embeddedなどを利用することもできます。
では詳細に入っていきましょう。Payara Micro
http://www.payara.fish/payara_micro
KumuluzEE
https://ee.kumuluz.com/
TomEE Embedded
http://tomee.apache.org/advanced/tomee-embedded/index.html
Dynamic load balancing
Oracle Container Cloudを使用した水平方向へのスケーラビリティは非常に単純で、アプリケーションの追加インスタンスを生成するだけです。これは、アプリケーション・コンシューマ(ユーザーまたは他のアプリケーション)が個々のインスタンスの詳細を取り扱う必要がないよう、ロードバランサを用意していて、ロードバランサの座標(ホスト /ポート)だけを知っていればよい場合に有効です。問題は、ロードバランサが新しく生成されたアプリケーションインスタンス/コンテナを認識しないことです。Oracle Container Cloudは統合スタックを作成することができます。これにより、バックエンド(この例ではREST API)と(HAProxy)ロードバランサ・コンポーネントの両方を単一ユニットとして構成し、簡単に管理および編成できるだけでなく、動的なHAProxyの化身(Avatar)のためにレシピを提供することができます。HAProxy on steroids
Oracle Container Cloud Githubリポジトリのアーティファクトを使い、confdおよびrunit用にカスタマイズされたDockerイメージの上に、特殊化された(Docker)HAProxyイメージを作成します。HAProxy Load Balancer Imageconfdは構成管理ツールであり、今回は実行中のアプリケーションインスタンスを動的に発見するために使用します。Oracle Container Cloudサービス内のネイティブ・サービス・ディスカバリに問い合せ、新しいアプリケーションインスタンスを検出する、新しいアプリケーション・インスタンスを検出するミニ・サービス・ディスカバリ・モジュールと考えてください。
https://github.com/oracle/docker-images/tree/0c7f9a90e4420e313f3aeba865cd064c2d138463/ContainerCloud/images/haproxy
confd - Manage local application configuration files using templates and data from etcd or consul
https://github.com/kelseyhightower/confd
runit - a UNIX init scheme with service supervision
http://smarden.org/runit/
Oracle® Cloud Using Oracle Container Cloud Service
Managing Entries in the Service Discovery Database to Enable Container Communication
http://docs.oracle.com/en/cloud/iaas/container-cloud/contu/managing-entries-service-discovery-database-enable-container-communication.html
Configuring our application to run on Oracle Container Cloud
Build Docker images
まず必要なDockerイメージを作成します。デモのため、Docker Hubのパブリックリポジトリ(abhirockzz)を使いますが、ご自身のパブリックリポジトリやプライベートリポジトリをお使いいただくことができます。Docker engineが起動していることを確認してください。
Build the application Docker image
Dockerfileは以下のような感じです。以下のコマンドを実行してイメージを作成します。FROM anapsix/alpine-java:latest
RUN mkdir app
WORKDIR "/app"
COPY target/occ-haproxy-swarm.jar .
EXPOSE 8080
CMD ["java", "-jar", "occ-haproxy-swarm.jar"]
docker build –t <registry>/occ-wfly-haproxy:<tag> . e.g. docker build –t abhirockzz/occ-wfly-haproxy:latest .
Build Docker images for runit, confd, haproxy
依存するイメージを順にビルドしていきましょう。まずは- GitHubのdocker-imagesを複製
oracle/docker-images
https://github.com/oracle/docker-images - ContainerCloud/images/build ディレクトリの vars.mk (Makefile) を編集し、 Docker Hubのユーザー名を入力します
vars.mk
https://github.com/oracle/docker-images/blob/0c7f9a90e4420e313f3aeba865cd064c2d138463/ContainerCloud/images/build/vars.mk
以下のコマンドを実行します。
cd ContainerCloud/images
cd runit
make image
cd ../confd
make image
cd ../nginx-lb
make image
Check your local Docker repository
ここまででローカルのDockerリポジトリに必要な全てのイメージがそろいました。Push Docker images
ではDockerイメージをレジストリにPushしましょう(今回の場合、筆者のパブリックDockerレジストリにPushします)。これにより、Oracle Container Cloudからアプリケーションスタックのデプロイ時にPullすることができます。Pushは以下のコマンドを実行します。各セットアップ毎にレジストリやリポジトリの名前を調整する必要があります。
docker login
docker push abhirockzz/occ-wfly-haproxy
docker push abhirockzz/haproxy
docker logout
Create the Stack
Stack作成のために、docker-composeに非常に似ているYAMLフォーマットの構成ファイルを利用します。この例では、サービス名(rest-api)をロードバランサ(HAProxy)サービスで参照しています。これは、Oracle Container Cloudサービス・レジストリ内のキーに関する情報をHAProxyサービスに提供します。このレジストリを使って(前述の)confdサービスが実際に新しいアプリケーション・インスタンスを自動検出します。8080は公開されたポート番号ですが、これ自体がサービスレジストリのキーの一部でもあるため、ハードコードされています。
StacksメニューからNew Stackを選択してプロセスを開始します。
Advanced EditorをクリックしてYAMLコンテンツを入力します。
これで個々のサービスが見えるはずです。Stack Nameを指定して[Save]をクリックします。
Initiate Deployment
Stacksメニューに戻って、新規作成されたStackを[Deploy]をクリックしてデプロイします。
ロードバランシングをテストするため、rest-api(バックエンド)サービスの3個のインスタンスをデプロイし、1個の負荷分散(HAProxy)サービスと紐付けます。
数秒後、全てのコンテナが実行中状態になっていることを確認できるはずです。今回は、この3個のサービスと1個のha-proxyロードバランサのインスタンスが実行中になっています。
Service Discoveryメニューをチェックして書くインスタンスが存在することを確認しましょう。前述の通り、これはconfdサービスがアプリケーションの新規インスタンスを自動検出することでイントロスペクトされています(自動的にこのレジストリに追加されます)。
Test
HAProxyを経由してアプリケーションにアクセスすることができます。HAProxyコンテナが実行しているホストのパブリックIPを知っておく必要があります。(下図の通り)バックエンドのアプリケーションにアクセスするためにポート番号8886が既にマップ済みです。以下のcURLコマンドを実行して確認しましょう。
9回呼び出し、(3個のインスタンス間で)負荷分散が動作していることを確認します。以下がその結果です。ハイライトされたテキストはレスポンスを返したインスタンスを指し示しています。3個のインスタンス間で負荷分散が均等になされています。for i in `seq 1 9`; do curl -w "\n" -X GET "http://<haproxy-container-public-IP>:8886/api/stocks?ticker=ORCL"; done
Scale up... and check again
スタックをスケールアップすることも簡単に繰り返し実施できます。デプロイメントに移動し、Change Scalingをクリックします。少々したら、追加されたアプリケーション・インスタンス(5個目のインスタンス)が確認できることでしょう。コマンドを再度実行し、負荷分散が想定通り動作していることを確認しましょう。