[Cloud] Microservices From Dev To Deploy, Part 3: Local Deployment & The Angular UI

原文はこちら。
https://blogs.oracle.com/developers/microservices-from-dev-to-deploy%2c-part-3%3a-local-deployment-the-angular-ui

この一連のエントリで、マイクロサービス・アプリケーションの構築方法を見てきました。Part 1でHelidonというOracleがリリースした新しいオープンソース・フレームワークと、Java(Microprofile)やGroovy(リアクティブ関数型スタイル)からの利用方法を知りました。
Microservices From Dev To Deploy, Part 1: Getting Started With Helidon
https://blogs.oracle.com/developers/microservices-from-dev-to-deploy-part-1-getting-started-with-helidon
https://orablogs-jp.blogspot.com/2018/10/microservices-from-dev-to-deploy-part-1.html
Part 2では、開発チームには強みと好みがあることを認識し、この架空のシナリオにおけるあるチームがNode.jsとExpressフレームワークを使ってマイクロサービスを開発したのに対し、もう一つのチームは、Oracleがリリースした、Fnというアプリケーションアーキテクチャにサーバーレスを追加するためのオープンソーステクノロジーを選択しました。
Microservices From Dev To Deploy, Part 2: Node/Express and Fn Serverless
https://blogs.oracle.com/developers/microservices-from-dev-to-deploy,-part-2:-nodeexpress-and-fn-serverless
https://orablogs-jp.blogspot.com/2018/10/microservices-from-dev-to-deploy-part-2.html
以下は全体像をイメージしやすくするためのアーキテクチャ図です。

人為的でつまらないシナリオかもしれませんが、今日のソフトウェアを構築する多くのチームの真の現実であるスキルと好みの多様性を適切に表していると思います。このシナリオの最終ゴールは、このアプリケーションの全ての個別のサービスをすべてOracle Cloudにすることですが、まもなくその段階に到達します。しかしその前に、開発されたこれらのバックエンドサービスがすべて統一されたフロントエンドで纏めてるところを見ていきましょう。

その前に、自宅で試す場合は、まずローカルのKubernetesクラスタにアクセスできることを確認してください。 テスト目的で、Raspberry Piを使ってクラスタを構築しました(手順はこちら)が、minikubeを使えばローカルのテスト環境を速やかに立ち上げることができます。構成したクラスタで作業するには、コマンドラインツールが必要なので、kubectlのインストールを忘れないでください。
Install Minikube
https://kubernetes.io/docs/tasks/tools/install-minikube/
Install and Set Up kubectl
install https://kubernetes.io/docs/tasks/tools/install-kubectl/

環境が整ったら、Part 1でHelidon SEとGroovyを使って天気予報のバックエンドサービスを構築したChrisのチームを見てみましょう。Gradleの 'assemble'タスクでデプロイ用にJARファイルを生成しますが、Helidonには他にもいくつかの便利な機能が含まれています:K8Sクラスタへの展開をスピードアップするためのDockerfileとKubernetesのためのyamlテンプレートを生成します。(MichikoのチームがPart 1で行ったように)Mavenのarchetypeを使用すると、ファイルは自動的にJARと共に 'target'ディレクトリにコピーされますが、ChrisのチームはGradleでGroovyを使用しているため、テンプレートをコピーするためのビルドスクリプトを少々変更し、スクリプト内のPathを少々変更する必要がありました。ここで使用したbuild.gradleスクリプトには、以下のタスクが含まれています。
task copyDocker(type:Copy) {
    from "src/main/docker"
    into "build"
    doLast {
        def d = new File( 'build/Dockerfile' )
        def dfile = d.text.replaceAll('\\$\\{project.artifactId\\}', project.name)
        dfile = dfile.replaceAll("COPY ${project.name}", "COPY libs/${project.name}")
        d.write(dfile)
    }
}
task copyK8s(type:Copy) {
    from "src/main/k8s"
    into "build"
    doLast {
        def a = new File( 'build/app.yaml' )
        def afile = a.text.replaceAll('\\$\\{project.artifactId\\}', project.name)
        a.write(afile)
    }
}

copyLibs.dependsOn jar
copyDocker.dependsOn jar
copyK8s.dependsOn jar
assemble.dependsOn copyLibs
assemble.dependsOn copyDocker
assemble.dependsOn copyK8s
Chrisチームがローカルビルドを実行すると、完全に機能するDockerfileとapp.yamlファイルを受け取り、サービスを迅速にDockerコンテナにパッケージ化し、そのコンテナをKubernetesクラスタにデプロイできます。プロセスは次のようになります。
  1. コードを書く
  2. テスト
  3. JARを作成(gradle assembleを実行)
  4. Dockerコンテナを作成(docker build / docker tagを実行)
  5. Docker RegistryへPush(docker pushを実行)
  6. Kubernetesデプロイメントの作成(kubectl createの実行)
quick screencastにまとめてみました。

バックエンドサービスの残りに対してプロセスを繰り返した後に、Avaが率いるフロントエンドチームはバックエンドサービスをAngular 6で作成してきたフロントエンドに統合できるようになりました。デプロイ済みのバックエンドのベースURLをenvironment.tsファイルに設定するところから作業は始まります。Angularはこのファイルを使って環境毎に異なる値を持つグローバル・アプリケーション変数を柔軟に管理できます。たとえば、environment.prod.ts ファイルには、ng build --prodを実行すると置き換えられる、本番環境用の値セットを保持できます。環境を指定しない場合、デフォルトのenvironment.tsを使います。そのため、チームは開発環境向けにこのファイルを使い、以下の値を設定しました。
export const environment = {
  production: false,
  stockApiBaseUrl: 'http://192.168.0.160:31002',
  weatherApiBaseUrl: 'http://192.168.0.160:31000',
  quoteApiBaseUrl: 'http://192.168.0.160:31001',
  catApiBaseUrl: 'http://localhost:31004',
};
チームは各マイクロサービスに対応するサービスを作成しています。こちらはweather.service.tsです。
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {environment} from '../../environments/environment';

@Injectable({
  providedIn: 'root'
})
export class WeatherService {

  private baseUrl: string = environment.weatherApiBaseUrl;

  constructor(
    private http: HttpClient,
  ) { }

  getWeatherByCoords(coordinates) {
    return this.http
      .get(`${this.baseUrl}/weather/current/lat/${coordinates.lat}/lon/${coordinates.lon}`);
  }
}
viewコンポーネントからサービスを呼び出します。
getWeather() {
  this.weather = null;
  this.weatherLoading = true;

  this.locationService.getLocation().subscribe((result) => {
    const response: any = result;
    const loc: Array<string> = response.loc.split(',');
    const lat: string = loc[0];
    const long: string = loc[1];
    console.log(loc)
    this.weatherService.getWeatherByCoords({lat: lat, lon: long})
      .subscribe(
        (weather) => {
          this.weather = weather;
        },
        (error) => {},
        () => {
          this.weatherLoading = false;
        }
      );
  });
}
全てのサービスについて完了したら、先祖返りしたホームページという企業ビジョンはまもなく現実のものになろうとしています。


これらの3個のエントリで、アイデアからバックエンドサービス作成、そしてそれらをAngular 6で作ったモダンなJavaScriptベースのフロントエンドに統合するまでという、TechCorpのインターネット・ホームページアプリケーションの開発を開発するという旅路を辿ってきました。次回のエントリでは、この技術的に多様なアプリケーションのOracle Cloudへのデプロイをご紹介します。

0 件のコメント:

コメントを投稿