🍋

AWSで実現するモダンアプリケーション入門 備忘録

2023/03/19に公開

はじめに

AWSで実現するモダンアプリケーション入門 備忘録

https://www.amazon.co.jp/dp/4297133261

モダンアプリケーションの定義

設計、構築、管理を継続的に見直し、常に変化を受け続けられるアプリケーションにするという開発戦略
変化を受け入れ続けられるための仕組みのことであり、目的ではなく手段のことである

ベストプラクティス

例えば、MVPを決めて市場にフィードバックをもらいながら形を作っていき、迅速に市場にフィットしたサービスを作りたい
そのためには管理を簡素化できる仕組み、例えば、サーバーレスにすることが方法の一つとして考えられる
(メンテナンスに払うコストを最小化でき、別の時間に注力することができる)
その他にも、ワークロードに適した方法を適宜選択する
具体的には、ビジネス開始時点で最速で要件を満たしたいであれば、モノリシックアーキテクチャを選択する
一方で、モジュラーアーキテクチャを採用し、コンポーネントごとに入れ替え可能にすることで柔軟に設計を変更できるマイクロサービス化を選択するということもある
このようなアプリケーション開発のための指針なるものが以下

  • The Twelve-Factor App
    • Herokuが考案したアプリケーション開発のためのベストプラクティス
  • Beyond the Twelve-Factor App
    • Pivotal社が提案したベストプラクティス
    • Heroku社のやつは考え方が古く、クラウドを使う点で考慮すべき観点が足りなかったなどがあった

モニタリングとオブザーバビリティ

コラムで書かれており興味深かった
モニタリングはエラーの検知のプロセス
オブザーバビリティはエラーの詳細の解析・分析
という区分けがしっくりきた(諸説あるとのこと)

サーバーレス

  • GoogleやAWSなど定義の表現は違えど概ね似ている
  • 柔軟なスケーリングと価値にあった支払い
  • プロビジョニング、スケーリング、キャパシティプランニングという作業に時間を費やさなくて良くなる考え方

パイプラインファースト

モダンアプリケーションはデプロイが頻繁に行われているのが正しいあり方
よって、CI/CDは必然的に多くなり、早ければ早い方が良いという

  • CI
    • AWS CodeBuild
      • LINTや自動テスト
      • ビルドの実行
  • CD
    • AWS CodePipeline
      • アプリケーションのデプロイプロセスの自動化
        • Blue/Greenデプロイやローリングデプロイなど

サービスメッシュ

マクロサービス文脈
各サービス間はAPIをインターフェースとしてやりとりする
つまり、間にインターネットが介在することになる
となると、通信は不安定になることを織り込んでシステム設計しないといけない
具体的には

  • リトライ・タイムアウト
  • サーキットブレーカー
  • ログやトレースの仕込み
  • 他のAPIを見つけるためのサービスディスカバリー

これらは共通して作らないと意味ないので、各サービスの共通基盤としてインフラチームが作ったりする
それをまるっとAWSにおまかせできるサービスが「AWS App Mesh」
ちなみに、App MeshはLambda対応してないので、ECSを使うことになる

サービスメッシュ導入する前に

  • インフラチームが既にサービス間通信の共通基盤を持っている
  • 各マイクロサービスは同じ言語やフレームワークで構成されている
  • メトリクスやログにSaaSを導入しており、各マクロサービスでSaaSが提供するライブラリを利用している

上記に当てはまる場合は、サービスメッシュで受けるメリットよりも、管理の複雑さなどのデメリットの方が大きいかもしれないので導入は注意が必要
サービスメッシュは通信を管理するための、コントロールプレーンが入るため、複雑になる
それだけではなく、アプリケーションと一緒にプロキシをデプロイする(データプレーン)必要がある
サービスメッシュを構成するために単純にシステムの複雑度は増すのは確実

  • コントロールプレーン:コンテナのデプロイやスケジューリングを管理する役割を持つもの(例:ECS)
  • データプレーン:コンテナ実行環境(例:EC2やFargate)

サービスディスカバリ

サービス間で相手のサービスを見つける仕組み
AWSではAWS Cloud Mapがある
特にスケールアウトする場合便利
また、ECSはタスクが増える毎にCloud Mapに自動で登録してくれるので便利
ALBでは機能がTooMatch or 設定のコスパ悪い場合、Cloud Mapに置き換えが可能かもしれないので積極的に検討する

サーキットブレーカー

用語覚えておく

  • クローズ
    • 正常な状態。トラフィックは流れている。
  • オープン
    • 異常を検知して、トラフィックを止めている状態。
    • ブレーカー(安全装置)が稼働している状態のイメージ
  • ハーフオープン
    • 限られたリクエストを送信して様子見している

BFF(Backend For Frontends)

API Gatewayパターンの拡張版
具体的にはクライアントの種別ごとに異なるエンドポイントを作る
背景として、モバイルとWebどちらも単一のエンドポイントにすると、API Gateway自体の複雑度が増してしまう(API自体がモノリシックとなる)
クライアントの種類が増えるにつれてその複雑度は高まってしまう
モバイルユーザ、業務向け管理画面、社内管理画面は、それぞれエンドポイントを分けるとか

非同期通信による疎結合な設計

同期的な通信の課題

  • クライアントがどうしても待ちぼうけになってしまう(APIの処理時間が長いとわかりやすい)
  • 裏側で複数のAPIをコールしていた場合、すべてが同期的通信していると、どこかで待ちが発生したら全体に影響してしまう
  • 一時的に高負荷状態になったら、サービス全体に影響する。各サービスの負荷対策も連動して考えないといけない

非同期の設計としてよく使われるのはキューモデルで、AWSではSQSがそれ
SQSの標準キューはほぼ無制限のAPI呼び出しができる(一方で、取り出すメッセージの順序は保証されない)

キューモデルは1:1でメッセージを送信する場合に有効
一方で、1:多でメッセージを送信する場合だったら、「パブサブモデル」が良い

パブサブモデル

  • パブリッシャー(送信側)がバス(EventBridge)やトピック(SNS)と呼ばれる場所にメッセージとしてイベントを送信
  • バスやトピックを登録しているサブスクライバーがメッセージを受け取る

イベントソーシング

ビジネスに重要なイベントはログとして残しておき、遡れるようにしておきたいという用途で使える
ここでいうイベントのログを耐久性のあるストレージに保存しておき、他のサービスに伝搬させるパターンのことを「イベントソーシング」という

イベントソーシングの実現例

  • DynamoDB
    • キー・バリューストアの特性を活かしてイベントをItemとして時系列に保存することができる
  • EventBridge
    • アーカイブ機能があり、保持期間を指定してイベントを保存できる
    • 保存期間を無制限にもできるので、イベントソーシングの要件に最適

Sage

サービスにまたがった整合性を維持するための仕組み
マイクロサービスだと、各サービス間でのデータ整合性をどう合わせていくが重要になる
RDBでいうトランザクションのロールバックの機能をサービス間レベルで行うイメージ

Sageにも2つパターンがある

  • Saga(コレオグラフィ)
    • 全体を統括する役割はいない。各サービスが自律的に他サービスと連携を取りながら対応するパターン
    • Amazon EventBridgeを使う例
      • 仮に決済サービスでエラーが出てリトライでも失敗したら、EventBridgeに購入取り消しのイベントを送信(補償トランザクション)
  • Saga(オーケストラレーション)
    • 全体を監視する役割がいる
    • Step Functionsがオーケストラレーターとして活用できる
      • Step Functions自身がステートマシンとして機能して、各サービスの実行ワークフローを管理できる

Discussion