クラウドアプリケーション10の設計原則

# はじめに
参考文献

https://www.amazon.co.jp/%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3-10%E3%81%AE%E8%A8%AD%E8%A8%88%E5%8E%9F%E5%89%87-%E3%80%8CAzure%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3%E3%82%AC%E3%82%A4%E3%83%89%E3%80%8D%E3%81%8B%E3%82%89%E5%AD%A6%E3%81%B6%E6%99%AE%E9%81%8D%E7%9A%84%E3%81%AA%E5%8E%9F%E7%90%86%E5%8E%9F%E5%89%87-%E7%9C%9F%E5%A3%81-%E5%BE%B9-ebook/dp/B0CKLFXV3B/ref=sr_1_1?adgrpid=165462347738&dib=eyJ2IjoiMSJ9.mx4tN5NKqRO4ECs0XpDZXEUOeJLbwnFQ847GWUT_Hk75W3IKNZDok9ZaiJEsJYmz7Bfmgc4edh_cWm7CwJrME_dDGeOozc-WOxRI3dZJTtBU3wbq4UPfnL4yxZi8SdxB.W3Z4HikpIlBHxeEG7dM8WkhNgF71eIpUQ1KL1ZwCiAM&dib_tag=se&gad_source=1&hvadid=705334048031&hvdev=c&hvlocphy=9198378&hvnetw=g&hvqmt=e&hvrand=9827256665255272783&hvtargid=kwd-2327407768739&hydadcr=27272_14738606&jp-ad-ap=0&keywords=%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B310%E3%81%AE%E8%A8%AD%E8%A8%88%E5%8E%9F%E5%89%87&mcid=7a1875093fd932ec9945b6d07733a59e&qid=1737474416&sr=8-1

「Azureアプリケーション10の設計原則」を元に、一般にクラウド上にアプリケーションやシステムを構築する際心にとめておきたい原則、陳腐化しにくい普遍的なクラウド設計の原理原則についてまとめた本。

ベストプラクティスを鵜呑みにするだけでなく、その裏側にある「原則」を理解せよと本書では言われている。

# 1.全ての要素を冗長化する
https://learn.microsoft.com/ja-jp/azure/architecture/guide/design-principles/redundancy

システムの可用性を確保するために、全ての構成要素を冗長化。サーバー、ストレージ、ネットワークなど各リソースを冗長化し、障害発生時でもサービスが継続できる仕組みを構築する必要がある。

### 推奨事項
1. ゾーンやリージョン間の冗長化
同一データセンター内だけでなく、複数の地理的リージョンや可用性ゾーンにリソースを分散配置します。
1. データのバックアップとレプリケーション
定期的なバックアップや、複数リージョン間でのデータ同期を行い、データ損失を防ぎます。
1. ロードバランサーの使用
負荷を複数のリソースに分散させ、個別のリソースが障害を起こしても影響を最小化します。
1. 障害時の復旧プラン（DR対策）
障害を想定し、迅速な復旧が可能な災害復旧計画（Disaster Recovery）を用意します。

# 2.自己復旧できるようにする
https://learn.microsoft.com/ja-jp/azure/architecture/guide/design-principles/self-healing

障害が発生してもシステムを自動復旧できるようにしておくことで、サービス停止時間を短縮。収益損失や顧客離れを防ぐため、迅速な復旧が不可欠。

### 推奨事項
1. 失敗した操作を再試行する（リトライ）
リトライの仕組みを備えておく。この際期待しない重複処理を防ぐため（たとえば「金融機関への入金処理を誤って２回実行」）に、リクエストをうけたキーがすでに処理済みか判断する冪等性を担保しておく。
1. リモート サービスを保護する (サーキット ブレーカー)
過剰なリトライを防ぐ。サービス呼び出しのエラー数が閾値を超えたら、リクエストにエラーを返す。
1. 失敗したトランザクションを補正する（Sagaパターン）
複数のデータストアを参照、更新するトランザクションが必要な場合、データの整合性は重要。特にクラウドでは複数のサービスや外部サービスを組み合わせてアプリケーションを作ることが多いため課題になりやすい。
「All or nothing」の分散トランザクションは避けて、失敗した操作を補正するための補正トランザクション（例: 購入処理の失敗時に、在庫を元に戻す、課金処理を取り消す。）を定義するのが推奨。

# 3.調整を最小限に抑える
https://learn.microsoft.com/ja-jp/azure/architecture/guide/design-principles/minimize-coordination

複数のインスタンスがリソースを共有する場合、何らかの手段でインスタンス間の調整が必要。
例：データベースの更新時のロック
更新時にロックを獲得できなかったインスタンスはその解放をまつことになる。調整はボトルネックを作り出し、スケールアウトを制限する要因になる。

### 推奨事項
1. 結果整合性を受け入れる。
即時整合性は求めず、データの更新が反映されるまで時間差を許容しますが、一定のタイミングで最終的に一貫性を達成する。たとえば分散トランザクションではなく、補正トランザクションパターンを採用する。
1. 非同期アーキテクチャを検討する
非同期処理では、コンポーネント間がリアルタイムで相互依存する必要がなく、処理をキューやイベント経由で進められるため、負荷の変動や遅延に柔軟に対応可能です。また、非同期モデルではコンポーネントごとに独立してスケールアウトでき、同期処理に比べて調整ポイントが減少します。これにより、システムの複雑性を低減し、スケーラビリティや可用性を向上させることができます。

# 4.スケールアウトできるようにする
https://learn.microsoft.com/ja-jp/azure/architecture/guide/design-principles/scale-out

クラウドでは以下の理由により、スケールアップよりスケールアウトが好まれる
- 拡張や縮小の際、サービスへの影響が小さい（スケールアップ・ダウンは一般的にサービス停止や再起動を伴う）
- 性能拡張に合わせて、可用性も高められる
- スケールアップは限界に達すると、プロバイダのサービス拡充を待たなければならない

アプリケーションを水平方向に拡張できるよう設計することで、クラウドの柔軟なスケーリングの利点を活用できる。負荷が増えたときはインスタンスを追加してスケールアウトし、負荷が減少すればインスタンスを減らしてスケールインする。

### 推奨事項
1. 自動スケール機能を利用する。
多くのクラウドサービスでは自動スケール機能を提供している。時間指定やメトリクス（CPU使用率、キュー内のメッセージ数）をトリガーとしてスケールアウトを実施する。

1. セッションアフィニティやスティッキーセッションに依存せず、セッション情報は外に持つ。
セッションアフィニティやスティッキーセッションとは、同じクライアントからのリクエストを常に同じサーバーに転送する仕組み。セッション管理を目的として従来から使われてきた仕組みだが、スケールアウトで仮想マシンやコンテナなどのインスタンスを追加した際にせっかく追加したインスタンスを活かしきれなくなり、クラウドの利点を損なう課題がある。できる限りセッション情報はRedisなど外部のセッションストアに格納し、どのインスタンスからでもアクセスできるようにする。

# 5.分割して上限を回避する

https://learn.microsoft.com/ja-jp/azure/architecture/guide/design-principles/partition

クラウドに限らず、コンピューターには数々の上限がある（CPU数のような物理的上限、同時接続数など論理的上限）クラウドサービスは、ユーザーがリソースを安全でフェアに共有できるようルールやポリシーのもと上限が定められている。

Azureの例
- 最大仮想マシン数：サブスクリプションごとに、リージョンあたり25,000
- 仮想マシンスケールセットあたりの最大仮想マシン数：1,000
- Azure SQL Database 最大データサイズ：100TB（Hyperscale Gen5）
- Azure SQL Database 最大同時セッション数：30,000（Hyperscale Gen5）
- Azure App Service プランあたりの最大インスタンス数：30（Premium v3）

この上限を回避したい場合は、**上限に達しないよう分割**すればよい。

### 推奨事項
1. データベース サイズ、データ I/O、または同時セッション数の制限を回避するには、データベースをパーティション分割。
1. 要求数やコンカレント接続数の制限を回避するには、キューまたはメッセージ バスをパーティション分割。
1. App Service プランごとのインスタンス数の制限を回避するには、App Service Web アプリをパーティション分割。

# 6.運用を考慮する
https://learn.microsoft.com/ja-jp/azure/architecture/guide/design-principles/design-for-operations

運用しやすいアプリケーションを作る。

以下はAmazon.comのCTO　WernerVogles氏がインタビューで語った言葉

> You build it, you run it. This brings developers into contact with the day-to-day operation of their software. It also brings them into day-to-day contact with the customer. This customer feedback loop is essential for improving the quality of the service.
> 著者訳：作った人が、運用する。これにより、開発者はソフトウェアの日々の運用に接します。また、顧客との日常的な接点も生まれます。この顧客とのフィードバックループは、サービスの品質を向上させるために不可欠です。

> The traditional model is that you take your software to the wall that separates development and operations, and throw it over and then forget about it. Not at Amazon.
> 著者訳：従来のモデルは、開発と運用を隔てている壁までソフトウェアを持っていき、壁の向こうへ放り投げ、忘れてしまうというものでした。Amazonでは、そうではありません。

### 推奨事項
- すべてを観測可能にする
システムが稼働した後、ログやトレースは重要な情報源となります。
**トレース**: システム内の処理の流れを記録し、ボトルネックやパフォーマンスの問題、障害箇所を特定するのに役立ちます。
**ログ**: アプリケーションの状態変化、エラー、例外などのイベントを記録します。
運用環境では必ずログを記録してください。これがないと、必要な情報を必要なときに取得できなくなります。

- 監視機能を導入する
監視機能は、アプリケーションの可用性、パフォーマンス、システムの正常性をチェックし、問題を把握するためのものです。
例えば、監視データを使えばSLA（サービスレベル契約）が守られているか確認できます。
監視はシステムが通常運用中に行われ、運用スタッフが問題を迅速に解決できるよう、できる限りリアルタイムで実施することが大切です。適切な監視により、重大なエラーが発生する前に問題を防ぐことが可能です。詳しくは「監視と診断」を参照してください。
- 構成をコードとして管理する(IaCなど)
構成ファイルをバージョン管理システムで管理し、変更履歴を追跡できるようにします。これにより、必要に応じて構成を以前の状態に戻すことも可能になります。

# 7.マネージドサービスを活用する。

https://learn.microsoft.com/ja-jp/azure/architecture/guide/design-principles/managed-services

クラウドを使いこなすコツの中でも効果が高いのは、すでにあるものは使う、プロバイダにタスクを任せること。マネージドサービスを活用し、何でも作ろうとせず、クラウドサービスが提供する部分を活かしましょう。

【参考】下記のデジタル庁のクラウドガイドラインにも下記の記述有

https://www.digital.go.jp/assets/contents/node/basic_page/field_ref_resources/e2a06143-ed29-4f1d-9c31-0f06fca67afc/5167e265/20230929_resources_standard_guidelines_guideline_01.pdf

> 1) マネージドサービスの活用によるコスト削減
> 旧世代のクラウド利用では様々な機能の実現のために、仮想サーバを構築し、ソフトウェアをインストールし、サーバの運用管理を行うことが一般的であった。すなわち、仮想サーバのクラウド利用料、ソフトウェアのライセンス・保守費用、運用管理の人件費が発生していた。
> 今日のスマートなクラウド利用においては、CSP が提供するマネージドサービスの機能を組み合わせることで多くの機能が実現可能であり、かつ保守・運用管理は CSP 側で行われることから、費用はマネージドサービスのクラウド利用料のみとなり、その金額は多くの場合、旧世代の数分の１といわれている。自らがサーバ構築をしないため、サーバ構築にかかる固定費が不要になることに加え、インフラ環境が完成されたサービスとして提供されるため、インフラ環境のテストや評価等の作業も大きく削減されるからである。


# 8.用途に適したデータストアを選ぶ。
リレーショナルデータストアベース以外にも以下のデータストアを選択できる。用途によって使い分けよう。
- ドキュメントデータストア
- キーバリューデータストア
- グラフデータストア
- 時系列データストア
- オブジェクトデータストア
- 外部インデックスデータストア

# 9.進化を見込んで設計する
成長に対応可能な計画を立てる。 
ソリューションでは、ユーザー数、トランザクションの量、およびデータ ストレージの現在のニーズがサポートされているとしても、主要なアーキテクチャを変更することなく、成長に対応できるようにする必要もあります。 また、ビジネス モデルやビジネス要件は時間の経過と共に変化していくということも考慮するようにしてください。 アプリケーションのサービス モデルやデータ モデルが柔軟性に乏しいと、新たなユース ケースやシナリオに合わせてアプリケーションを改良することが困難になります。

# 10.ビジネスニーズを忘れない
https://learn.microsoft.com/ja-jp/azure/architecture/guide/design-principles/build-for-business

ビジネスニーズは技術の現場から遠ざかりやすい。
しかし設計の決定はすべてビジネス要件によって正当化される必要があります。 クラウドアプリケーションを設計する際には、このことに留意することがきわめて重要。

- ビジネス目標を定義する。
ビジネス目標（RTO、RPO、MTOなど）を定め、それをアーキテクチャの決定に反映させます。例えば、RTOやRPOが低い場合、ゾーン冗長アーキテクチャを採用することが考えられます。一方、高いRTOやRPOが許容される場合、冗長性を増やすとコストが無駄になる可能性があります。
- ビジネス モデルとコストを合致させる。 
システムの寿命は、コストがビジネス モデルとどれだけ効果的に合致しているかによって左右されます。 アーキテクトはソリューションが価値を提供するディメンション (収益性など) を特定することで、アーキテクチャが投資に対する価値を最大化し、ビジネス要件に沿った投資収益率 (ROI) を実現できます。

# 感想
クラウドは各サービスの知識ゲーのイメージがあったが、普遍的な重要ポイントを理解できた。
ビジネスニーズもできるだけ定量化して抑えておくことが、意思決定にも重要だというのが印象に残った。