(レポート) ARC309: モノリシックからマイクロサービスへ:クラウド内のアーキテクチャパターンの進化 #reinvent

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

丹内です。掲題のセッションをレポートします。

スピーカー

背景

初期(2007年)のアーキテクチャはRails/Postgres/memcached/workerを使ったモノリシックなものでしたが、2011年の段階ではRailsを使いつつもJavaが増え、サービス間のメッセージもKB単位になるのど増大したそうです。
2015年現在はLOSA(lots of small app)なマイクロサービスになっているそうです。このLOSAは聞いたことが無かったのですが、検索してみるとGiltのブログが出てきます。

sereiceは何をするのか

スクリーンショット 2015-10-09 17.32.41

1つのサービスは、以下の性質を備えている必要があります。

  • container
    • JVM
    • httpによるjson enddpoint
    • web application framework
    • アプリケーションコード
    • モニタリング
    • ロギング
  • DB
  • 他サービスへメッセージを投げる方法(宛先)

ディスカバリ

スクリーンショット 2015-10-09 17.36.22

上のように、zookeeperでlookupしているそうです。
この他に、DNSを使ったり、Netflix/eurekaを使っても実現できます。

技術と組織について

システムを開発する組織についても言及していました。
マイクロサービスで開発する場合は、DBまでそれぞれのチームで決めるようにします。機能だけ別チーム・別サービスでDBは共通、というようなことはしません。つまり、技術レイヤではなくビジネスで分けます。
それによって、

  • RDBのスキーマ管理でチーム間の調整がなくなる
  • そのチームが担当するサービスの特性に応じてDBを使い分けることができる

という利点があります。その時には以下の様な事を考えて実装する必要があります。

  • consumerサイド
    • providerが故障しても失敗を適切にハンドリングする
    • providerに負荷をかけない(exponential backoffなど)
  • provierサイド
    • サービス内メトリクスをアグリゲーターに送信する
    • 後方互換性
    • 実装を意識させないインタフェース

これを実装するにあたり、API Gatewayを使うことで、コストを下げつつ統一化することができます。

Data Management

ところで、DBを独立させるという点で、トランザクションをどうしようかという問題が発生します。
そこで、以下の方針で解決していきます。

  • pessimistic model: トランザクションマネージャ。
  • optimistic model: eventual consistencyを受け入れる

もちろん、トランザクションがあまり発生しない単位で設計することが前提であるとは思います。

サービス間でのデータの同期は、以下のように行います。

  • pull model: バッチゲットAPIを作る
  • push model: S3に置いて、もう片方は一定時間ごとにチェックする
  • pub/sub model: KinesisやSQSを使う

deployment

codedeployやCIサービスを使います。ここらへんは試行錯誤しているようでした。 初めて知ったのですが、ECSへの複数コンテナデプロイにElasticBeanstalkが使えるようです!!!ドキュメントはこちらです。

また、サービスごとにビルドパイプラインを作ったり、1インスタンスごとに1コンテナ、というプラクティスがあります。
ビルドパイプラインについては、マイクロサービスは各サービスを個別にビルド・デプロイするものだからだそうです。
1インスタンス1コンテナについては、サービスが使用するリソースを正確に測定するためです。(複数サービスが1インスタンスで動くと、どのサービスがどれくらいリソースを使っているか詳細にわからない)
「1インスタンス1コンテナ」の部分は、「1サービス1LambdaFunction」でも良いそうです!!他のセッションでも「Lambda function is micoservice without server」ということですね!!

I/O Explosion

マイクロサービスでは、サービスのカスケードによってIOが上がります。
client chacheを入れてサービスへの問い合わせをやめたり、よく呼ばれるサービスのリソースを増やしたり、サービスが返すデータを以降のリクエストにInjectionするなどの工夫が必要となります。

感想

マイクロサービス実装のプラクティスがたくさんありました! また、「1サービス1LambdaFunction」は何度もいろんな人達が話していて、本当にこの流れが来ていると思います。
あと、ECSバックエンドのBeanstalkについては「またお前か!」って感じです(良くも悪くも)。