キャッシュとロードバランシング

サイトダウンの原因は主に機器障害とアクセス集中（負荷増大）であり、これらを解決する手法としてキャッシュとロードバランシングが広く使われている。

## 1. キャッシュとは何か？
キャッシュとは、最初にサーバから取得したレスポンス（HTML、CSS、画像など）を、ブラウザや中間サーバが一時的に保存しておき、同じリクエストを再度受けたときに、その保存済みデータを利用して高速にレスポンスを返す仕組み。

具体的な処理の流れは以下の通り：
1. 最初のリクエスト時
    1. クライアントがサーバにリクエストを送る。
    1. サーバは処理（DBのデータ取得や計算など）をしてレスポンスを作成。
    1. レスポンスを返すと同時に、このレスポンスをキャッシュとして一時的に保存。
1. 次回以降のリクエスト
    1. 同じリクエストが届くと、サーバはまずキャッシュにデータがあるか確認する。
    1. キャッシュにデータが存在し、有効期限（TTL：Time To Live）内なら、サーバは新たな処理をせずにキャッシュされたレスポンスをそのまま返す。
    1. キャッシュが無い、または期限切れなら、サーバは再度データを処理して新しいレスポンスを生成し、キャッシュを更新する。

### キャッシュが持つ利点
- クライアントに高速でレスポンスを返せる（サーバへの問い合わせ削減）
- サーバの負荷軽減（レスポンス生成の処理を減らす）
- システム全体の可用性が向上（アクセス集中時も安定）

### キャッシュの分類
HTTPのキャッシュは大きく分けて2種類ある。

#### プライベートキャッシュ
- 特定のクライアントにのみ保存される（通常はブラウザ内に保存）。
- 個人専用の情報をキャッシュ可能（例：ユーザー別の表示内容）。
- 他人がアクセスできないため情報漏洩リスクが低い。
#### 共有キャッシュ
- 複数ユーザー間で共用され、主に次の2種類に分けられる。
  - プロキシキャッシュ
    - 主にネットワークトラフィック削減目的で設置。
    - 開発者の管理外にあるため、HTTPヘッダー（Cache-Control）で慎重に制御が必要。
    - HTTPS化の進展で、中間キャッシュとしては利用されにくくなっている。
  - マネージドキャッシュ
    - 開発者が明示的に配置するキャッシュ。
    - リバースプロキシ（例：Varnish）やCDN、サービスワーカーのキャッシュAPIなど。
    - キャッシュ内容を明示的に削除可能であり、積極的なキャッシュ戦略が採用可能。

### キャッシュ制御の仕組み（Cache-Controlヘッダー）
キャッシュの動作はHTTPヘッダーを使って制御されることが一般的。
代表的なのは Cache-Control ヘッダーで、以下のような指示を指定可能。

- max-age=秒数
    - キャッシュを何秒間有効にするか指定。
    - 例：Cache-Control: max-age=3600（1時間キャッシュ）
- If-Modified-Since / Last-Modified
    - レスポンスが最後に更新された日時を基準にキャッシュが最新かを判断するために使用するヘッダー。更新されていない場合はサーバは304 Not Modifiedを返し、キャッシュ再利用を促す。
- ETag
    - コンテンツごとの固有識別子で、クライアント側で保存されたキャッシュとサーバのデータが一致しているか比較し、キャッシュが最新かどうかを確認するために使用。
- no-store
    - 絶対にキャッシュを保存しないことを指定する。
    - 機密情報や動的データに適している。
- no-cache
    - 毎回サーバに再確認（検証）を要求するが、キャッシュ自体は保存可能。
- private
    - 特定のユーザー専用（ブラウザのみ）にキャッシュすることを指定。
- public
    - 共有キャッシュにも保存して良いことを指定。

### キャッシュの性能
キャッシュの性能は「キャッシュヒット率」が重要である。
以下に求めるためのキャッシュヒットとキャッシュミスについて記載する。

- キャッシュヒット
    - キャッシュにリクエストされたデータが存在し、即座にクライアントに返せる状態のこと。サーバ処理を省略できるので高速。

- キャッシュミス
    - キャッシュにデータが存在しない（または期限切れ）状態。サーバでの処理が必要となり、レスポンスまでの時間がかかる。

ヒット率を高めるには、キャッシュの期限や対象データの粒度（細かさ）を工夫するほか、Cache-Controlの指定だけでなく、ETagやIf-Modified-Sinceを活用して効率よくキャッシュを再検証させる戦略をとることも重要である。

> 参考：[MDN - HTTP Caching](https://developer.mozilla.org/ja/docs/Web/HTTP/Guides/Caching)

## 2. ロードバランシング（負荷分散）とは何か？
ロードバランシングとは、アプリケーションをサポートする複数サーバ間でネットワークトラフィックを最適に分散させ、特定のサーバに負荷が集中しないように調整する仕組み。
ロードバランサーは、ユーザーと多数のサーバの間に位置し、トラフィックを適切に割り振ることで、アプリケーションの可用性、スケーラビリティ、セキュリティ、パフォーマンスを高める。

### ロードバランシングのメリット
インターネットトラフィックの自動制御によって以下のようなメリットがある。
- 可用性向上
  - サーバが故障しても、自動で他のサーバにトラフィックを振り分けるため、サービスの停止を防げる。
- スケーラビリティ向上
  - サーバの追加・削除が柔軟に行え、トラフィック増減に対して柔軟に対応可能。
- セキュリティ向上
  - DDoS攻撃など大量アクセスを分散処理し、システムを攻撃から守る。
- パフォーマンス向上
  - トラフィックを最適なサーバに分散させることで、応答時間やレイテンシを低減。

### ロードバランシングアルゴリズムの種類
ロードバランシングのアルゴリズムは、大きく以下の2つに分類される。

#### 静的ロードバランシング
現在のサーバ状態に関係なく、固定ルールに従って分散する。
- ラウンドロビン
  - リクエストを順番にサーバへ振り分ける方式。
- 重み付きラウンドロビン
  - サーバごとに重み（キャパシティ）を設定し、性能の高いサーバに多く振り分ける。
- IPハッシュ方式
  - クライアントのIPアドレスをハッシュ化し、その結果に基づいてサーバを決定。

#### 動的ロードバランシング
サーバの現在の負荷や応答時間などの状態に基づいて、リクエストを分散する。

- リーストコネクション
  - 最も接続数が少ないサーバにリクエストを送信する方式。
- 重み付きリーストコネクション
  - サーバごとに異なる接続数を処理可能として、重み付きで判断する方式。
- 最小応答時間方式
  - 応答時間が最も短いサーバを選択する方式。
- リソースベース方式
  - 各サーバにエージェントを配置し、CPUやメモリなどのリソース状況をリアルタイムに把握して割り当てる方式。

### ロードバランシングのタイプ
リクエストでチェックする内容に応じて、以下のように分類される。
- アプリケーションロードバランシング
  - HTTPヘッダーやセッション情報を見てリクエストを分散。
  - 特定のアプリケーション機能に特化したサーバグループにルーティング。
- ネットワークロードバランシング
  - IPアドレスなどのネットワーク情報を基準に分散。
  - 大量のトラフィックを高速に処理できる。
- グローバルサーバーロードバランシング
  - 地理的に離れた複数のデータセンター間で分散。
  - 最も近いデータセンターにルーティングし、レイテンシを最小化する。
- DNSロードバランシング
  - ドメイン名に紐づく複数リソース間で負荷を分散する仕組み。
### ロードバランシング技術の種類
- ハードウェアロードバランサー
  - 専用機器を用いて高性能かつ大量のトラフィックを処理する。
  - 導入コスト・保守コストが高いが、安定性が高い。
- ソフトウェアロードバランサー
    - ソフトウェアベースで柔軟にスケール可能。
    - クラウド環境との親和性が高く、初期コストが安い。

> 参考：[AWS - ロードバランシングとは](https://aws.amazon.com/jp/what-is/load-balancing/)

## まとめ
- キャッシュとロードバランシングの組み合わせが重要
- キャッシュによってサーバ負荷を軽減し、ロードバランシングによってトラフィックを最適に分散することで、システムの信頼性やパフォーマンスが大幅に向上する。
- 両者を正しく理解し組み合わせることで、システムダウンのリスクを大きく減らすことが可能になる。