Journey to Adopt Cloud-Native Architecture Series 感想

Architecture AWS

Journey to Adopt Cloud-Native Architecture Series は、現在 3 本の記事が公開されている未完のシリーズとなっており、モノリシックなアーキテクチャをクラウドネイティブなアーキテクチャ(マイクロサービス)に段階的に進化させていくという、非常に王道的な内容になっています。2021 年 3 月からの連載ということで、情報の鮮度も新しめのところが嬉しいですね!


#1 – Preparing your Applications for Hypergrowth

この記事では、まずは前提の確認を行っています。元記事は こちら

目指すべき「Hypergrowth」というのは、ブラックフライデーのように急激に需要が伸びることで、ユーザーへの影響を最小限にしながらスケーリングを実現するためには、マイクロサービスや Purpose-built データベース、自動デプロイパイプライン、サーバーレスなど、いわゆるモダンな原則を導入する必要があると説明されています。クラウドの場合は固定的なアーキテクチャをずっと使いまわしていくのではなく、ビジネスの成長度合いやその時々のニーズに合わせてアーキテクチャを進化させていこう、という考え方が重要なんですね!

このシリーズで扱うシステムの現状のアーキテクチャは、Auto Scaling 付きの EC2 と、RDS for PostgreSQL という、非常にベーシックな 3 層アーキテクチャで(元記事の Figure 1 を参照のこと)、マルチ AZ 構成にもなっているし、これはこれで大きな問題は無いように思います。しかし、Hypergrowth に対応するにあたり、このアーキテクチャにはいくつか問題点があると指摘されています。

  • アプリケーションが 1 つの Java アプリに集約されており(容量は 5 GB!)、細かい粒度でスケーリングできないことと、立ち上げに 5 分以上かかることから Auto Scaling が間に合わないことが懸念される
  • データベースはプライマリ側にのみアクセスしているため、この部分のスケーリングには限界がある
  • 不要な JOIN を避けるために大きなテーブル(数百カラム!)としているが、それにより IO の効率が落ちている
  • ビルドからテストを走らせるのに 2-3 時間はかかっている他、開発・テスト・本番環境のパイプラインが別々に存在しており、調整が必要
  • 単一アカウント構成としているため、クォータへの抵触の心配が出てくる
  • 等々(元記事を参照のこと)

確かに、急激なアクセス増に対応するには、迅速性という観点でもうワンステージ上を目指す必要がありそうですね。また、拡張後のシステムにおいても、これまでと同様に運用していく必要があるため、運用面でのスケーリングにも注意を払っていく必要がありそうです。

こういった状況をふまえ、次の記事では、システム全体のスループットを向上させる方法について検討していきます。

#2 – Maximizing System Throughput

この記事では、主にデータベース層をリアーキテクトして、システム全体のスループットの向上を図ります。元記事は こちら

まずはデータベース層にリードレプリカを追加して、読み取りワークロードをオフロードすることが紹介されています。RDS for PostgreSQL の場合は、5 台までリードレプリカを追加できますね。また、キャッシュ層を追加して、データベースへのそもそもの問い合わせ数を減らす戦略も紹介されています。AWS の場合、こういったキャッシュには ElastiCache が使えますね。どちらも、データベースへの問い合わせで多い読み取りのワークロードをいかに削減・分散させるか、という観点でのソリューションということになります。ただ、これらを採用する際は接続先のエンドポイントが複数になるため、アプリ側の改修コストもかかる点には注意が必要ですね。

接続数を減らすという観点では、コネクションプールの導入も要検討ポイントです。というのも、頻繁に接続・切断を繰り返すとそれだけでデータベースのリソースを使うことになりますし、かといって多くの接続をアイドル状態のまま繋ぎっぱなしにしておいてもリソースへの影響があるからだそうです。コネクションプールはアプリ側で自前で用意してもよいですが、AWS では RDS Proxy という選択肢がありますね。私自身は使ったことがないのであまり詳しくはわかりませんが…。

効率的にリソースを利用するという観点では、クエリチューニングも有効な選択肢です。RDS には Performance Insights という機能があり、有効にしておくだけで、どのクエリの実行にどの程度時間が消費されたかが分かるようになっており、その結果をもとにクエリのチューニングを進めることができるようになっています。また、例えば、いわゆる OLAP 的なクエリがリソースを圧迫している場合は、そのクエリをリードレプリカ側で実行するようにするなど、負荷分散する際の手がかりとしてもこの情報は使うことができます。

これらの対策をしても依然としてプライマリインスタンスへの負荷が心配、もしくは書き込みワークロードの分散が必要、という場合は、シャーディングを検討する。ただ、残念ながら RDS のマネージド機能ではシャーディングは実施してくれないので、この実現にはユーザー側での作り込みが必要になります。

この記事では、EC2 部分は Auto Scaling でスケーリングできるからいいとして、ネックになりがちなデータベース部分のスループットを高めるためのテクニックが紹介されていました。RDS のマネージド機能で行ってくれる部分はあるにせよ、だいたいがアプリ側の改修を必要とするものになるので、いかに事前のアーキテクチャ設計が大切かということがよくわかりますね!

次の記事では、パフォーマンス以外の観点から、現状のアーキテクチャからの進化を検討していきます。

#3 – Improved Resilience and Standardized Observability

この記事では、システムの復元力と可観測性を高めるテクニックについて紹介しています。元記事は こちら

モノリスなアプリケーションの場合、すべてのコンポーネントがごった煮なので、あるイベントが予期せぬ別の場所にも作用することがあり、それらは事前のテストでは潰し切るのが難しく、結果として、システム障害を引き起こしてしまうことがあります。抜本的な脱モノリスについては一旦置いておくとして、こういった障害から速やかに復旧するにはどうすればよいでしょうか。

まずキーとなるのが、マネージド機能の利用です。例えば、RDS ではクロスリージョンリードレプリカという機能が提供されており、他のリージョンへの非同期レプリケーションを自動で実施してくれます。S3 にもクロスリージョンレプリケーションという機能がありますね。また、AWS Backup というサービスを利用することで、EC2 や EBS、RDS から定期的にバックアップを取得してくれたり、それを他のリージョンへコピーしたりしてくれます。まずはこういったマネージド機能を使って、自動でデータのコピーを他のリージョンにしておき、何かあった際に素早く待機系から立ち上げられるように準備をしておきます。

サーバー間のメッセージのやり取りを、SQS や SNS を使って疎結合化することも有効です。こうすることにより、障害発生時の影響範囲を低減することができます。また、こういった構成を取る場合、後続のサーバーを Lambda 等に置き換えて、イベントドリブンなデザインパターンにすることも有効です。徐々に、マイクロサービスの香りがしてきましたね!

このように、障害発生への備えをした上で、あとは正常性の診断や障害発生時の迅速な調査のために、システムの可観測性を高めておきます。AWS では CloudWatch にメトリクスやログが収集されますが、収集しておわりではなく、リアルタイムでそれらを解析できるように準備しておくことが重要です。メトリクスについては CloudWatch だけである程度のことができますが、ログについては Kibana や Athena、Elasticsearch Service あたりが役に立つでしょう。

次の記事では、現状のアーキテクチャからの進化を検討していきます。


現時点までで、ひとつひとつのテクニックについて特に目新しいものはありませんが、それがこういった一連のシリーズにまとめられていること、そして多くの参考リンクが元記事には含まれていて、それらも含めたひとつのリファレンスとしてこのシリーズは一読の価値ありです!また、具体的なサービスや機能についてまでは押さえられなくても、その考え方や指針だけでも参考になる部分は多いように感じました。

タイトルとURLをコピーしました