本資料は、Weaveworksが公開しているマイクロサービスのデモアプリケーションSock Shopを利用(on OpenShift)して、マイクロサービスを体験するハンズオンです。
https://github.com/microservices-demo/microservices-demo
Sock Shopのデザインは下記の通りで、Java, NodeJS, Goなどとマイクロサービスの特徴であるポリグロットを体現しています。詳細はこちら。
- openshiftクラスタ
- Google Chrome
- ocコマンドのインストール
- curlのインストール
- jqのインストール (recommended)
- postmanのインストール (optional)
本レポジトリのマニフェストファイルは、SCCの変更やcluster-adminを持っていなくてもOpenShift上で動くように修正しています。
$ oc apply -f complete-demo.yaml
deployment.extensions/carts-db created
service/carts-db created
deployment.extensions/carts created
service/carts created
deployment.extensions/catalogue-db created
service/catalogue-db created
deployment.extensions/catalogue created
service/catalogue created
deployment.extensions/front-end created
service/front-end created
deployment.extensions/orders-db created
service/orders-db created
deployment.extensions/orders created
service/orders created
deployment.extensions/payment created
service/payment created
deployment.extensions/queue-master created
service/queue-master created
deployment.extensions/rabbitmq created
service/rabbitmq created
deployment.extensions/shipping created
service/shipping created
deployment.extensions/user-db created
service/user-db created
deployment.extensions/user created
service/user created
$ oc get pod
NAME READY STATUS RESTARTS AGE
carts-db-86b89bcb4c-m68xh 1/1 Running 0 57s
carts-ffc5d77cd-9vf84 1/1 Running 0 56s
catalogue-6d8895f8b9-tjxk8 1/1 Running 0 52s
catalogue-db-746b88dc5c-mfg8p 1/1 Running 0 54s
front-end-f975554b6-f9qrc 1/1 Running 0 51s
orders-65df94c9f5-786hf 1/1 Running 0 48s
orders-db-5ff5cdd64c-cv4cb 1/1 Running 0 49s
payment-f5dcc89c5-6k2jl 1/1 Running 0 46s
queue-master-787b68b7fd-sjsxb 1/1 Running 0 45s
rabbitmq-7db7568778-89t2h 1/1 Running 0 43s
shipping-5c6867f94f-tzwdg 1/1 Running 0 42s
user-6866b4bcf4-rbr7p 1/1 Running 0 38s
user-db-78c5b86bb8-njsz8 1/1 Running 0 40s
Routeオブジェクトが作成され、Sock Shopにアクセスできます。
$ oc get route
NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD
front-end front-end-sock-shop.apps.8aad.example.opentlc.com front-end web None
ブラウザを起動して、作成したrouteのURLに接続して以下のようなSock Shopの画面が返ってくるか確認しましょう。
まずは、Sock Shopのサービスをブラウザから触って概要を理解しよう。
- ユーザ登録をする
- デフォルトでユーザは登録されていない
- カタログから靴下を検索、閲覧する
- カートに入れてみる
- カートの中身を確認する
- ペイメントと住所を登録せずに、何かをオーダーする
- ペイメントの登録する
- 住所の登録する
- もういちどオーダーする
- オーダーの詳細をする
Sock Shopで利用されているデータを書き出してみましょう。 後ほど実際にデータベースの構造を見ていきますが、現時点でどんなデータがどこにあるか意識しておくといいでしょう。
どのサービスがどのようなデータを保持しているかは、非常に重要です。 どのサービスがデータベースをもっていて、どのような情報をもっているか確かめてみましょう。
- catalogue(mysql)
- user(monogo)
- cart(mongo)
- order(mongo)
例として、データ構造の確認方法を記載します。
registry.gitlab.com/mosuke5/debug-container
は、mysqlとmongodbのクライアントをインストールしてあるCentOSベースのイメージです。
$ oc run debug --image registry.gitlab.com/mosuke5/debug-container -it /bin/bash
# mysql -uroot -pfake_password socksdb -h catalogue-db
mysql>
mysql> show tables;
+-------------------+
| Tables_in_socksdb |
+-------------------+
| sock |
| sock_tag |
| tag |
+-------------------+
3 rows in set (0.01 sec)
mysql>
mysql> desc sock;
???
# mongo -u sock-user -p password user-db/users
> show collections;
???
> db.customers.find()
???
# mongo -u sock-user -p password carts-db/data
???
# mongo -u sock-user -p password orders-db/data
???
APIの仕様はどのように定義すればいいでしょうか。また、どのようにその定義を確認したら良いでしょうか。
OpenAPIやSwaggerぜひ学んでみましょう。
Sock ShopのAPIドキュメント
https://microservices-demo.github.io/api/index
APIの開発や検証では、欠かせないツールがあります。 CurlやPostmanの使い方はよく覚えておくことをおすすめします。 詳細な使い方は、ここでは割愛しますが、本ページに出てくるいくつかの基本的な項目について記載します。
curlではcurl https://google.com
と指定すると
デフォルトではGETメソッドを利用します。
システムのAPIではGETのほかにPOSTやDELETEなどのメソッドを使うことも多くあります。
-X
オプションで指定することができます。
curl -X POST https://xxxxx/user
POSTなどのメソッドを利用する場合は、リクエストともにデータを送信することがよくあります。
例えばユーザ情報の登録APIにおいては、登録するデータを送信する必要があります。
データの形式はAPI仕様によるので、必ず確認してください。
下記では、jsonでname
という項目が必要な場合の例です。
$ curl -XPOST \
-d '{"name":"mosuke5"}' \
-H 'Content-Type:application/json; charset=UTF-8' \
https://xxxxx/user
ユーザエージェントやコンテンツタイプなどの指定でHTTPヘッダーを追加することがあります。
$ curl -H 'User-Agent: hoge' https://xxxxx/
APIによっては、認証が必要なことがあります。 例えば、ユーザAの個人情報がユーザBから取得できてしまってはいけません。 認証の方法もAPI仕様によるので、必ず確認しましょう。 本ワークショップでは、クッキーを利用するのでその方法を紹介します。 詳しくは、「ログイン」の項目で実践してみましょう。
curl -XGET -c cookie.txt https://xxxxx/login
フロントエンドアドレスを環境変数に指定しておきます。
$ export FRONTEND_ADDRESS=<your-frontend-address>
カタログ情報はログインなしでも実行できる簡単なAPIを実行してみよう。
APIドキュメントを見ながらURIとパラメータを確認するといいです。
商品ID 3395a43e-2d88-40de-b95f-e00e1502085b
についても検索してみよう。
商品のオーダーなどは当然ながらログインした状態でないと実行できません。
試しに、ログインセッションを持たないまま、オーダーAPIを実行してみるとログインしてくれとエラーが返ってきます。
$ curl -XGET $FRONTEND_ADDRESS/orders
{"message":"User not logged in.","error":{}}
ログインには"username:password"をbase64でエンコードした値が必要です(該当コード)。Authorization
という名前のHTTPヘッダーにBasic <エンコードした値>
を追加してログインAPIを実行することができます。
base64でエンコードした値は、コマンドラインで生成するか、こちらのようなBase64エンコードをしてくれるWebサービスで生成しましょう。
API経由でカートに商品を追加してみましょう。 その後にカートの中身を確認してみましょう。
同じ要領でAPI経由でオーダーしてみよう。 その後に、オーダーしたものがオーダーリストに入っているかAPI経由で同じく確認してみましょう。
フロントエンドサービスの役割を考えてみよう。
ひとつひとつのAPIがどんなものかわかってきたところで、フロントエンドサービスのコードをのぞいてみよう。
- メリット
- アプリケーションの内部仕様を隠蔽できる
- クライアントからみて、各サービスの接続先を気にしなくて良い
- クライアントサイドを簡素化
- クライアントからのリクエスト数の削減
- 認証認可などのオフロード
- デメリット
- レスポンスタイムの増加
- コンポーネントが増えることによる複雑化
- ボトルネックの可能性
- Gatewayのモノリシック化
API ゲートウェイ パターンと、クライアントからマイクロサービスへの直接通信との比較
例えば、オーダー詳細をブラウザからみてみよう。
オーダーの情報はもちろん商品の情報も表示されています。しかし、オーダーAPIではitemのidしか返していません。
どのようにしてitemの情報を取得しているか、 ブラウザのデベロッパーツール(検証モード)から確認してみましょう。
また、このデータの取得の方法は、モノリスなサービスの場合と比べてどうか、対策する方法があるか考えてみましょう。
マイクロサービスアーキテクチャでは、サービス間の通信をどのように行うかは重要な選択の1つです。
Sock Shopでも、アーキテクチャデザインの図を見ると、shippingサービスはRabbitMQに対してデータを送り、queue-masterが処理していることがわかります。
shipping
サービスとqueue-master
サービスのPodのログを見ながら、画面上からオーダー処理を行ってみましょう。
ログからキューへの書き込みおよび、キューからの受信を確認できるはずです。
また、非同期型の通信を利用するメリットについても考えてみましょう。
マイクロサービスの回復性について考えてみます。
cartsサービスを落としてみて、どんな影響があるか確認してみよう。
$ oc scale --replicas=0 deployment/carts
- オーダーはできるか?
- 他のコンポーネントへの影響は?
- ユーザ体験はどう変わったか?
cartsサービスを落としたあと、UI上からカートボタンが消えたのに気づきましたか?
これは、マイクロサービスでよくあるデグレードの実装が行われているからです。
できる人は、実際にデグレードの実装が行われているコードを探してみましょう。
ブラウザのデバッグツールを開いて、cartsサービスへの通信状況を見てみましょう。
アクセスの度にcartsサービスのタイムアウトを待っているのがわかるのではないでしょうか。
サーキットブレーカを実装した場合にはどのような動きになるか考えてみよう。
マイクロサービスのスケーリングについて考えてみます。
マイクロサービスでは特定のサービスのみをスケールすることが容易であることが特徴の1つです。
ためしにフロントエンドサービスをスケールさせてみてみましょう。
$ oc scale --replicas=3 deployment/front-end
フロントエンドのコンテナイメージを変更してデプロイしてみよう。
サンプルで、背景色を変更したフロントエンドのイメージ(mosuke5/front-end:master-bd5039f4
)を用意しました。
続いて、トレーシングを体験するためにjaegerなどのコンポーネントをデプロイします。
$ oc apply -f tracing/jaeger.yml
$ oc expose service/jaeger-query
$ oc get route
NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD
jaeger-query jaeger-query-sock-shop.xxxxx jaeger-query query-http None
jaeger-query
のURLに接続し下記のような画面にアクセスできれば成功です。
トレーシングコンポーネント起動後に、もう一度Sock Shopで購入などの様々なアクションを実行しましょう。検索からorders
サービスで検索をし、orders: http:/orders
を探してみましょう。
paymentサービスに障害が起きたと仮定し、paymentサービスを落としたあとに、もう一度購入操作をしてみましょう。
この複雑な処理のなかでもどこでエラーが起きたか一目瞭然に確認することができます。