「サービスを止めない」は、運用に入ってから初めてその重さを実感する。
開発中は「落ちたら直せばいい」と思いがちだが、本番運用が始まると1分のダウンタイムがユーザーの離脱や信頼の損失に直結する。『24時間365日 サーバ/インフラを支える技術』では、高可用性設計の考え方が体系的に整理されており、インフラを本格的に学ぶきっかけになった。
SPOFとは何か
**SPOF(Single Point of Failure:単一障害点)**とは、そこが止まるとシステム全体が止まるコンポーネントのことだ。
高可用性設計の出発点は「SPOFを見つけて排除する」ことだ。
# SPOFがある構成(危険)
クライアント → Webサーバ(1台) → DB(1台)
# SPOFを排除した構成
クライアント → ロードバランサ → Webサーバ × 2台 → DB(マスター/スレーブ)
Webサーバが1台しかない場合、そのサーバが落ちた瞬間にサービス全体が止まる。複数台構成にすることで、1台が落ちても残りが処理を引き継ぐ。
Active-Standby vs Active-Active
冗長化の方式には大きく2種類ある。
Active-Standby(待機冗長)
メイン機が動いている間はサブ機は待機。メイン機が落ちたらサブ機が引き継ぐ。
| 項目 | 内容 |
|---|---|
| コスト | サブ機は待機中コストがかかる |
| 切り替え速度 | フェイルオーバーに数秒〜数十秒かかる |
| 向いているもの | DB(マスター)・ステートフルなコンポーネント |
Active-Active(負荷分散冗長)
複数台が同時に稼働し、ロードバランサが負荷を分散する。1台が落ちても残りが処理を継続。
| 項目 | 内容 |
|---|---|
| コスト | 全台が稼働するため効率的 |
| 切り替え速度 | ほぼ瞬時(ヘルスチェックで除外) |
| 向いているもの | Webサーバ・APIサーバ・ステートレスなもの |
ステートレスにできるかどうかがActive-Activeにできる条件だ。セッション情報や状態をサーバ内に持っていると、どのサーバに振られるかによって挙動が変わってしまう。
フェイルオーバーの仕組み
障害時に自動で切り替わる仕組みがフェイルオーバーだ。
ヘルスチェック
ロードバランサは定期的に各サーバの死活確認(ヘルスチェック)を行う。応答がなければそのサーバへのルーティングを止め、正常なサーバにのみ振り分ける。
# ロードバランサのヘルスチェック設定(概念)
チェック間隔: 30秒
タイムアウト: 5秒
失敗しきい値: 3回連続で失敗したらアウト
ヘルスチェックの間隔と失敗しきい値の設定が重要で、厳しすぎると一時的な遅延でも切り離されて過剰に縮退し、緩すぎると障害のサーバへのルーティングが続く。
DBのフェイルオーバー
DBのフェイルオーバーはWebサーバより複雑だ。マスター昇格(スレーブをマスターに昇格させる)のタイミングで、未同期のデータが失われるリスクがある。
AWS RDSのMulti-AZ構成では、フェイルオーバーが自動化されており、通常1〜2分程度で切り替わる。
# RDS Multi-AZ の構成
マスター(AZ-a) ←同期レプリケーション→ スタンバイ(AZ-b)
マスター障害時: スタンバイが自動でマスターに昇格
エンドポイント: 変わらない(アプリ側の変更不要)
セッション管理の落とし穴
Active-Active構成でWebサーバを複数台にしたとき、セッション情報の扱いに注意が必要だ。
スティッキーセッション(危険):同じユーザーのリクエストを常に同じサーバに振り続ける方式。サーバが落ちたときにセッションが消える。根本解決ではない。
セッションの外部化(正しい対応):セッション情報をRedisなどの外部ストアに保存する。どのサーバに振られても同じセッションを参照できる。
// Expressでのセッション外部化例
import session from 'express-session';
import RedisStore from 'connect-redis';
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: process.env.SESSION_SECRET!,
resave: false,
saveUninitialized: false,
}));
マルチAZ構成でSPOFを排除する
AWSでは、複数のAvailability Zone(データセンター)にリソースを分散させることで、データセンター単位の障害に耐えられる。
# シングルAZ構成(AZ障害でサービス停止)
クライアント → ALB → EC2(AZ-a)→ RDS(AZ-a)
# マルチAZ構成(AZ障害でも継続)
クライアント → ALB → EC2(AZ-a)
→ EC2(AZ-b)
→ RDS マスター(AZ-a)+ スタンバイ(AZ-b)
コストは増えるが、本番サービスでマルチAZを避ける理由はほとんどない。AZ障害は年に何度か実際に起きており、対策していないシステムは必ず影響を受ける。
治験システムで「止められない」要件に向き合ったこと
治験(臨床試験)のシステムには「止められない」という圧力が一般的なWebサービスとは比較にならないほど強くかかる。
被験者への投薬スケジュールや有害事象の記録が止まることは、患者の安全に関わる問題になりうる。モニタリング訪問の直前にシステムが落ちれば、製薬会社との信頼関係に直結する。「1分のダウンタイムが信頼の損失につながる」という話は他の業種でも聞くが、医療系では文字どおりそれが現実だ。
最初に本番システムを触ったとき、構成はWebサーバ1台・DB1台のシンプルなもので、明らかにSPOFだらけだった。前任者は「今まで落ちたことない」と言ったが、落ちていないのは運が良かっただけで、それはリスクが存在しないこととは違う。
改善のためにまず取り組んだのがDBのMulti-AZ化だった。RDS Multi-AZに移行してフェイルオーバーを自動化したとき、製薬会社の担当者から「DR(ディザスタリカバリ)対策が確認できた」という言葉をもらった。技術的な設計が、外部監査の評価に直結した経験だ。
もうひとつ痛感したのはセッション管理の問題だ。Webサーバを複数台に増やしたとき、スティッキーセッションで一時しのぎしていた設計が悲鳴を上げた。1台がメンテナンスに入るたびにユーザーが強制ログアウトされ、クレームが来た。本書で「セッションの外部化」を学んでRedisに移行したことで、ノードを自由に増減できるようになった。
まとめ:高可用性設計のチェックリスト
設計時に確認すべき項目を整理する。
- WebサーバはActive-Active構成で複数台か
- DBはマスター/スレーブ構成またはManaged DBのMulti-AZか
- [ ]セッションは外部ストアに保存しているか(スティッキーセッション依存ではないか)
- [ ]ロードバランサ自体がSPOFになっていないか(AWSのALB/NLBは内部的に冗長化済み)
- [ ]複数のAZにリソースが分散されているか
- [ ]ヘルスチェックの間隔・しきい値は適切か
高可用性設計は「障害が起きないようにする」のではなく「障害が起きても止まらないようにする」という発想の転換が重要だ。