マイクロサービスのデモ環境
概念の理解に、サンプル環境は欠かせません。
そこでAWS Kubetnetes(EKS)の環境を作成し、マイクロサービスのサンプル(Sock Shop)を立ち上げる という記事を書いたのですが、このマイクロサービスのサンプル、https://github.com/microservices-demo/microservices-demo/の構造がわからなかったので、勉強がてらこのデモ環境がどのように構成されているかを記述してみます。
一応公式の文書はこちらにあります。
随時補筆しますが、当然のことながら常にウォッチしているわけではないので直ぐにソースと解説の内容が乖離するかもしれません。。
デモのデプロイスクリプト
microservices-demo/deploy/kubernetes/complete-demo.yaml を使うのですが、このスクリプトを含むリポジトリには特にマイクロサービスのソースは含まれません。
このyaml で使われているイメージは、すでにDockerHubのリポジトリ(例:weaveworksdemos/carts:0.4.8)のようにビルドされたコンテナイメージがアップされています。
ビルドする元になったソースは、https://github.com/microservices-demo配下にそれぞれ配置されているという事です。
全体像
いわゆるPolyglotというやつで、複数言語を使用しています。
入口(フロントエンド)
フロントエンドは、そのまま front-end というリポジトリに配置されており、これはnode.js のプロジェクトとなっています。このデモでは、サービスメッシュ(Istio)のようなものを使っていません。Istioを使った例だとGoogleのマイクロサービスデモのようなものがあります。
node.js はパッケージマネージャ npmを使用し、そのパッケージマネージャによって package.json が参照されます。 ここで server.js がメインとして指定されていますので、server.js を参照して処理が実行されます。
node.js にてHTTPリクエストの振り分けに使われるデファクトは、express.js です。
当初のGETリクエストはexpressの static 関数によりpublic/ に置かれた資材により、index.htmlが表示されます。
その他 各マイクロサービスへのAPIの名前のパスが呼ばれた場合に、 api/フォルダ配下にある各マイクロサービス名のフォルダ内のindex.js で用意されたモジュールにより、処理の振り分けが行われます。
振り分け先は api/endpoints.js に記述されたURL、すなわち、http://(マイクロサービス名)/ (例:util.format("http://user%s/cards", domain))に転送されていきます。
ログイン
Index.html内は divタグにて分かれ、靴下のプロダクトを表示するカルーセル以外はさらに topbar.html navbar.html footer.html が読み込まれます。
その内 topbar.html にてドロップダウン内にログインまたはレジスターメニューが表示され
、ログイン処理ができます。Cookieにてログイン判断がなされます。
この時、login() またはregister() は client.js に記述され、AJAX処理がなされます。
url としてlogin として呼び出されるのは 実は http://user/login です。
ユーザー関連
user コンポーネントはGo言語で作られ、Go Kitという MicroService用のライブラリを使用しています。
このマイクロサービスは、ユーザーに関する事のみをつかさどります。
ユーザーに関する情報はすべてMongoDBに登録されます。
Go Kitでは サービス、エンドポイント、ミドルウェア、トランスポートというレイヤがあり、サービスにビジネスロジックを書き、エンドポイントにそのサービスに入る入口を書き、トランスポートで ハンドラ(今回の場合HTTPハンドラ)から エンドポイントに接続してやり、ミドルウェアにてログ等の出力関連をまとめます。
それらのソースがapi 配下に配置されています。
例えば Loginであれば service.go にfunc Login というサービス、
endpoint.go に LoginEndpointという エンドポイント、
transport.go に HTTP GET /login から LoginEndpointへのハンドラが記述されています。
また、middleware.go にアプリログ、Prometheus用ログメトリクスのミドルウェア定義がなされています。
その他のGo
Goで作成されたその他の Catalogue, Payment もGo Kitを使用しているのですが、ソースの構造はcmd/~/main.go から始まっており、関数構造も若干異なっています。
その他のJava
その他のJavaプロジェクトは、SpringBootで作られています。
src配下のController のAnnotationを見れば、大体のHTTP のハンドラがわかります。
これらは、すべてDockerFileによりビルド後にコンテナ化され、独立化して動きます。
マイクロサービスの要諦
結局のところ、マイクロサービスというのは、昔コンポーネントをオブジェクト指向で開発し、ビジネスロジックをCORBAやEJBといったもので役割で分割していたものを、API(RESTful)なコンポーネントに分割してコンテナ化したものと言えます。 SOAとかなり近い概念ですが、さらなる細かい分割が可能です。
その細かい分割の運用に際しては、現在凄い勢いでログ、分散トレース、メトリクス収集等のOSS網が発達しています。これらをどの言語でも使えるように、きわめて汎用化した形でInjectionするようなモジュールが、どの言語にもフレームワークとして備わっています。今回の例ですとSpring BootとGo Kitがそれにあたります。
モノリスとマイクロサービス
ここで、モノリスでは全体を見て影響範囲を検討していたものが、マイクロサービスでは自分のコンポーネントだけを見て開発もできるため、迅速に開発ができる反面、変更にかかるコストは使用している側が検討しなくてはならなくなります。 今回のSock Shopの例を見ても、結局フロントエンドが各サービスのAPIを呼んでいる為、サービス側が変更されるとフロントエンド側も変更する必要があります。これは別段gRPCを使用している Googleのマイクロサービスデモ も同じです。
ただし、これは極めて合理的であり、現在ほとんどのサービスが、RESTFulなサービスであることを考えると、これはAPI Economyを実現する一つの手段であるかと思います。