(レポート) ARC305: モノリシックからマイクロサービスへ Gilt社の場合 #reinvent

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

はじめに

マイクロサービスどうなの?今までとどう違うの?ということでセッションに参加してみました。

Giltは、米国で展開しているオンラインショッピングサイトです。スピーカーの1人は、Gilt社のシニアソフトウェアエンジニアです。

アジェンダは以下

  • なぜマイクロサービスか?
  • マイグレーションのアプローチと考慮点
  • Giltによる、AWS上でのマイクロサービスの取り組み
  • アーキテクチャーパターンとベストプラクティス

ECサイトのトラフィック

顧客向けのアプリケーションは大体どこも同じように夜の時間帯に大きなピークを迎えます。オンプレであれば最大ピークを見越してハードを用意しますが、クラウドであればいつでもリソースを調達できます。しかし、実際のところは余裕を持って大きなインスタンスが構えていることも多いかと思います。

SS 2016-12-02 23.37.13

Giltのインフラ事情

まずはじめにGilt社のインフラの歴史についてお話頂きました。2007年の創業時には、Railsベースのシンプルなアプリケーションで、memcacheとPostgreSQLを使っていました。次に、2011年は、バックエンドのシステムを分割し始めます。商品サービス、注文サービス、カートサービスなどといった単位でモノリシックなサービスをJavaを使って作りました。そして、2015年は、マイクロサービス化しています。Scalaで書いた短か目のコードのサーバー100以上に分割して、t2.microで動かしています。tシリーズは性能が一時的にバーストする安価なインスタンスです。

SS 2016-12-02 23.38.03

モノリシックとマイクロサービス

Giltは、数年を掛けてモノリシックからマイクロサービスにしました。以前のモノリシックでは、シンプルなデプロイで、内部モジュール間のリファクタリングを行い、正常か異常かの2値で、垂直スケールして、単一テクノロジーを用いていました。マイクロサービスにしたことによって、部分的なデプロイを行い、強いモジュールの堺があり、部分的な障害時も全体が動き、水平スケールして、技術の多様性が出ました。

SS 2016-12-02 23.38.48

組織構造

マイクロサービス化することで小さな単位のチームが複数できました。

SS 2016-12-02 23.39.05

アーキテクチャー

複数のマイクロサービスは、それぞれ異なるエンドポイントとなるドメインを持ち、UIから呼ばれます。

SS 2016-12-02 23.39.40

場合によっては、API Gatewayでラップしても良いかもしれません。

SS 2016-12-02 23.40.39

スタック

それぞれのマイクロサービスは、Dockerコンテナ上で動き、CloudWatchのアラームからSNSを通知して自動的な処理に繋げたり、CloudWatch Logsを用いてシステムが正しく動いているかログのモニタリングを行います。

SS 2016-12-02 23.41.25

インスタンス

小さな単位で行っているため、バースト対応のt2インスタンスを多用しています。

SS 2016-12-02 23.42.47

集約タイプ

複数のマイクロサービスを集約して動作させるような場合、様々な実現方法があります。プル型、プッシュ型、Pub/Sub型、複合型などです。

SS 2016-12-02 23.44.45

ディスカバリー

多数のマイクロサービスがあると、どのサービスがどのドメイン名か分からなくなってしまいます。また、様々な理由からドメインを他のリソースに変更することも考えられます。そんために、サービスレジストリーというサービスを用意しています。

SS 2016-12-02 23.45.10

API Gatewayの活用

API Gatewayは、モノリシックかマイクロサービスか、裏側の状況を利用者に意識させません。はじめにモノリシックで作ったものをマイクロサービス化してもインタフェースが同じであれば良いです。

SS 2016-12-02 23.45.45

APIのバージョン管理

上記では、インタフェースが変わらなければとありましたが、実際のところはAPI自体の変更や追加が起こります。通常のリリースでやって良いことは、メソッドの追加、オプションパラメータの追加、非推奨化、または破壊的な変更の"相談"のみです。やってはいけないことは、メソッドの削除やリネーム、必須パラメータの追加や削除、破壊的な変更の"要求"です。このようなことは、メジャーバージョンアップまで待ちましょう。

SS 2016-12-02 23.46.31

継続的なデプロイ

CIツールなどを使って、各マイクロサービスに対して頻繁に軽量な単位でのビルドを繰り返します。

SS 2016-12-02 23.48.18

Blue/Green

CodeDeployを用いて開発と本番のスイッチをしながら、動作テストを行っています。

SS 2016-12-02 23.49.22

ログ集約

多数のインスタンスからログが発生しますので、最終的にはElasticsearchに入れてKibanaで分析をしています。

SS 2016-12-02 23.51.32

ログの標準化

様々なマイクロサービスが呼ばれ、それぞれでログが残りますが、一連の処理においてログファイルのレコードを追うのは大変です。時刻でソートしたとしても、様々なズレが生じます。そこで、UUIDを用いて追跡できるようにするのはベストプラクティスです。

SS 2016-12-02 23.52.08

キャッシュ永続化

軽量なリソースで効率よく動作させるためにはキャッシュが重要です。ローカルキャッシュもひとつのやり方ですが、水平スケールするインスタンスでキャッシュを共有するためにElastiCacheを用いています。

SS 2016-12-02 23.54.38

API Gatewayでは、リードスループットに対するキャッシュに対応しています。

SS 2016-12-02 23.54.50

まとめ

技術的なテクニックの他に、マイクロサービス化を推進するということは、組織のあり方を変え、チーム毎のコミュニケーションが重要になり、チームの一員として正しい行動をしようと発言し、セッションを終了しました。今回のre:Inventでは、AWS BatchやAWS Step Functionsなど、マイクロサービスの順序や分岐などを制御できるようになってきています。今後、よりマイクロサービスの考え方を押さえておく必要が出てくると思います。

参考資料

AWS re:Invent 2016: From Monolithic to Microservices: Evolving Architecture Patterns (ARC305)