精読「AWSで実現するモダンアプリケーション入門」(1)
AWSで実現するモダンアプリケーション入門
AWSを活用したモダンアプリケーション開発に興味がある方にとって非常に有益な一冊です。初心者から中級者向けにバランスよく解説されており、実践的な知識を得ることができる点が評価できます。
関連記事
モダンアプリケーションとは何か
モダンアプリケーションの定義
モダンアプリケーションとは、アプリケーションの設計、構築、管理を継続的に見直し、変化を受け入れ続ける開発戦略のこと
モダンアプリケーションのベストプラクティス
- モニタリング
- サーバレステクノロジー
- リリースパイプライン
- モジュラーアーキテクチャ[1]
アプリケーション開発におけるベストプラクティスを適用
The Twelve-Factor App
2012年頃にHeroku社のエンジニアによって提唱されたウェブアプリケーションを実装するためのベストプラクティス
項目 | 説明 |
---|---|
I. コードベース | バージョン管理されている1つのコードベースと複数のデプロイ |
II. 依存関係 | 依存関係を明示的に宣言し分離する |
III. 設定 | 設定を環境変数に格納する |
IV. バックエンドサービス | バックエンドサービスをアタッチされたリソースとして扱う |
V. ビルド、リリース、実行 | ビルド、リリース、実行の3つのステージを厳密に分離する |
VI. プロセス | アプリケーションを1つもしくは複数のステートレスなプロセスとして実行する |
VII. ポートバインディング | ポートバインディングを通してサービスを公開する |
VIII. 並行性 | プロセスモデルによってスケールアウトする |
IX. 廃棄容易性 | 高速な起動とグレースフルシャットダウンで堅牢性を最大化する |
X. 開発/本番一致 | 開発、ステージング、本番環境をできるだけ一致させた状態を保つ |
XI. ログ | ログをイベントストリームとして扱う |
XII. 管理プロセス | 管理タスクを1回限りのプロセスとして実行する |
Beyond the Twelve-Factor App
2016年頃にPivotal者のエンジニアによって提唱されたベストプラクティス。The Twelve-Factor Appを尊重しつつ、12種類のプラクティスを更新し、そして新しく3種類のプラクティスを追加し、計15種類のプラクティスから構成されている。
番号 | 項目 | 説明 |
---|---|---|
1 | One codebase, one application | 1コードベース、1アプリケーション |
2 | API first | APIファースト |
3 | Dependency management | 依存関係管理 |
4 | Design, build, release, and run | デザイン、ビルド、リリース、実行 |
5 | Configuration, credentials, and code | 設定、機密情報、コード |
6 | Logs | ログ |
7 | Disposability | 廃棄容易性 |
8 | Backing services | バックエンドサービス |
9 | Environment parity | 環境一致 |
10 | Administrative processes | 管理プロセス |
11 | Port binding | ポートバインディング |
12 | Stateless processes | ステートレスプロセス |
13 | Concurrency | 並行性 |
14 | Telemetry | テレメトリ |
15 | Authentication and authorization | 認証/認可 |
コードベース
- コードベースとアプリケーションを1:1の関係にする
Beyond the Twelve-Factor App を元にした アプリケーション開発のプラクティス考察より
依存関係
- 依存関係を宣言する
The Twelve-Factor Appでは、システム全体にインストールされるパッケージが暗黙的に存在することを認めない。すべての依存関係を厳密に宣言することが重要。
設定
-
設定とコードを分離する
設定とは、環境ごとに異なる値のこと(DB情報[2]、API情報[3]、アプリケーション機能情報[4]、アプリケーション情報[5]等) -
設定を外部化する
AWSでは、AWS systems Manager Parameter Store[6]やAWS Secrets Manager[7]を使うことで、設定を外部化できる。
APIファースト
-
すべてのアプリケーションをAPIにする
APIのインターフェース仕様があることで、関係者との議論が容易になる
データの取得による状況の可視化
ビジネスデータ
経営陣が将来の計画のために利用したり、マーケティングチームがキャンペーンの効果を測定するために利用されるデータ。(アクティブなユーザー数、新規の会員登録したユーザー数、書籍の販売数、閲覧数、滞在時間など)
重要なのは、これらのデータを取得できるようにモダンアプリケーションが構築されていること。ビジネスの状況を可視化するためにどのようなデータが必要で、必要なデータを取得するためにどのようにアプリケーションを実装し、アーキテクチャを構成するべきかをあらかじめ検討しておく。
運用データ
サービスの運用状況を可視化するために必要なデータ。(運用担当者の呼び出し回数、設定変更など運用作業の依頼として起票されるチケット数、チケットが完了するまでの経過時間、一日あたりのデプロイ数、サービスの可用性等)
システムデータ
インフラやアプリケーションの状況を可視化するために必要なデータ。(リクエスト数、リクエストのエラー数、リクエストの処理時間など)
- REDメソッド[8]:リクエスト駆動のサービスであれば適応できるメトリクス(特にマイクロサービスアーキテクチャを採用する場合は効果的)
- USEメソッド[9]:キューとそれを処理するジョブで構成されるようなサービス
オブザーバビリティ(可観測性)
オブザーバビリティとは、「システムの内部で何が起きているのか」を説明できるシステムの能力を示している。すでに紹介したメトリクスに、ログとトレースデータを加え他3本柱という考え方がある。
注目される最新の監視体制「オブザーバビリティ」とは?モニタリングとの違いなどより
サーバーレスやコンテナテクノロジーによる運用改善
サーバーレスとコンテナのワークロード比較
サーバーレスとコンテナの使い分けの1つの指針は「アプリケーション開発に、より多くの時間や人を投資できる選択肢はどれか」という観点で整理する考え方。つまり、Lambdaで要件を満たせない場合[10]にECSやEKSの採用を検討すること。
シナリオによるサーバーレスワークロードの構成例
ユーザーが書籍を購入した後に、会員ページから領収書をPDFファイルとしてダウンロードできる機能
- 大規模リクエストに対応可能か:SQSの標準キューは1秒あたりほぼ無制限のAPI実行をサポートしているし、Lambda関数も自動的にスケールするため
- アプリケーションのエラーに対応可能か:SQSの可視性タイムアウト[11]で重複処理を回避
- 冪等性[12]の考慮ができるか:生成するPDFのファイル名を何かしらの仕様で固定するアプリケーションの工夫で回避
- モニタリングできるか:SQSのメトリクス(ApproximateAgeOfOldestMessage[13]、ApproximateNumberOfMessagesVisible[14]等)やCloudWatch Logsのログ情報などからモニタリング可能
- 拡張性があるか:他の下流システムにイベントを連携したい場合、EventBridgeをイベントバスとして利用する
シナリオによるコンテナワークロードの構成例
ポイントの付与や消費、現在のポイント残高や履歴の表示といった機能が必要。将来の拡張性を考慮し、ポイント機能をAPIとして提供する。
- 大規模リクエストに対応可能か:APIはElastic Load Balancingを経由しているため、問題ない。また、Auto Scalingを利用することでECSで実行するコンテナアプリケーションの数を自動で増減できる
- アプリケーションのエラーに対応可能か:APIのレスポンスにエラー情報が含まれるため、クライアント側で適切なエラーハンドリングを実装できる
- 冪等性の考慮ができるか:ポイント付与や消費等の更新処理において、APIリクエストに購入IDのような購入情報を一意に特定するパラメーターを定義し、DB側でそれらをプライマリキーに設定することで、ポイントの更新処理を冪等な操作にできる
- モニタリングできるか:Elastic Load BalancingのApplication Load BalancerはREDメソッドメソッドのメトリクスがCloudWatchメトリクスに発行される。また、CloudWatch Container Insightsを利用すれば、これらのメトリクスから問題を検知した場合に調査するためのデータとして、詳細なリソースメトリクスを取得できる。さらに、CloudWatch Logsやのログ集約やX-Rayを利用したトレーシングデータの集約なども取得可能
- 拡張性があるか:ポイント機能はAPIとして提供するため、APIの実処理を行うアプリケーション部分は必要に応じて再構成が可能。(例.APIのインターフェイスは維持し、バックエンドをコテなからサーバレスに置き換えられる)
CI/CDパイプラインによるデリバリーの自動化
CI/CDパイプラインに必要となる機能
要件にあったデータベースの選択
データベースに求める機能と要件
- データ量:データサイズやデータ件数
- データ増減パターン:大きく増減するのか
- 保持期間:いつまで保持する必要があるのか
- アクセスパターン:参照、追加、更新、削除など。(Read Heavy?Write Heavy?)
- 形式:保存するデータの種類や形式(リレーショナル、キーバリュー、インメモリ、ドキュメント、ワイドカラム、グラフ、時系列、台帳)
Purpose-built databaseとは何か?
データベースの選択は、「データベースXはアプリケーションで実現したい要件に最適だから」という理由で選択すべき。
Purpose-built databases: The model for building applications in the cloudより
シナリオによるデータベースの選択
- 書籍データ:書籍データには多くの決まった情報があり、他のデータと紐づけて検索をすることもあるため、RDSが最適。さらに、アクセスパターンとして参照が多くなるパターンであると想定されるため、ElastiCacheも組み合わせて使う
-
お気に入りデータ:レコードが大量になる可能性があるので、データ量の観点でスケーラビリティ性に強みのあるDBが良さそう。また、データサイズも少なめなため(ユーザーID、書籍ID、タイムスタンプ)、DynamoDBが最適。
- お気に入り登録、削除は プライマリーキーを設定してアイテムの操作(PutItem,GetItem,DeleteItem等)をすれば実現できる
- もう少し自由に操作したい場合、セカンダリインデックス[15]を使う。
Amazon DynamoDBとは何かをわかりやすく図解、どう使う?テーブル設計の方法とはより
参考
-
モジュラーモノリス、マイクロサービス等 ↩︎
-
エンドポイント、アカウント、データベース名など ↩︎
-
エンドポイント、パラメータなど ↩︎
-
ポイント付与率、表示項目数、フィーチャーフラグなど ↩︎
-
ログレベルなど ↩︎
-
設定を一元的に管理できる機能 ↩︎
-
アプリケーションなどに必要なシークレット情報の保護を支援するサービス ↩︎
-
リクエスト数、リクエスト数、リクエストのエラー数、リクエストの処理時間の頭文字 ↩︎
-
タスクの処理件数、キューイングされているタスクの件数、エラー件数の頭文字居 ↩︎
-
Lambda関数のタイムアウト設定は最大で15分なので、それ委譲の実行時間が想定されるアプリケーションでは採用が難しくなる ↩︎
-
可視性タイムアウトとは、 SQS のキューに入ったメッセージが処理開始直後に重複して処理されないように、処理中の場合、一時的に他のプロセスからは、メッセージが存在していることを見えないようにする設定 ↩︎
-
ある操作を1回行っても複数回行っても結果が同じであることをいう概念 ↩︎
-
キューの中で最も古い削除されていないメッセージのおおよその経過期間 ↩︎
-
キューの中で取得可能なメッセージのおおよその件数 ↩︎
-
ローカルセカンダリインデックス(LSI)、グローバルセカンダリインデックス(GSL) ↩︎
Discussion