独立サイトの負荷分散:マルチインスタンス構成、ヘルスチェック、セッション維持、フェイルオーバー

独立サイトで負荷分散を導入するきっかけは、日次アクセスが安定して5万を超え、4コア8Gの単一サーバーでCPUが長期的に60%以上になるか、あるいは一度「サーバーが落ちてサイト全体が開けない」という痛い目にあったときです。合格ラインは、少なくとも2つの応...

独立站负载均衡:多实例、健康检查与故障转移Load balancing: multi-instance, health check, failover 反直觉:会话保持不是必须的,无状态化才能真正横向扩展Counter-intuitive: sticky sessions hurt scaling; go stateless 负载均衡器 LBLoad Balancer L4 TCP / L7 HTTPL4 TCP / L7 HTTP 应用实例 AApp Instance A 健康 200 · 权重 50%Healthy, weight 50% 应用实例 BApp Instance B 健康 200 · 权重 50%Healthy, weight 50% 应用实例 CApp Instance C 3次失败 · 自动摘除Unhealthy, drained 健康检查:每10秒请求一次 /health,连续3次失败摘除,连续2次成功恢复Health: GET /health every 10s; 3 fails out, 2 oks in 会话保持:默认关闭,登录态放Redis或JWT;只有老系统实在改不动才开cookie粘性Sticky off; sessions in Redis/JWT 故障转移:单台宕机LB在10秒内摘除,流量自动打到健康实例,用户无感知Failover: LB drains dead node in 10s, user sees nothing 至少跨2台不同物理机/可用区;同机房单机断电=白配Spread across AZs, not one rack
負荷分散:正常なインスタンスに振り分け、障害インスタンスは自動で切り離し

独立サイトの負荷分散:マルチインスタンス構成、ヘルスチェック、セッション維持、フェイルオーバー

結論から言うと:独立サイトで負荷分散を導入するきっかけは、日次アクセスが安定して5万を超え、4コア8Gの単一サーバーでCPUが長期的に60%以上になるか、あるいは一度「サーバーが落ちてサイト全体が開けない」という痛い目にあったときです。合格ラインは、少なくとも2つのアプリケーションインスタンスを異なる可用性ゾーンに配置し、10秒ごとにヘルスチェックを実行し、3回連続で失敗したら自動的に切り離し、フェイルオーバーを10秒以内に完了させることです。直感に反するのは、セッション維持(sticky session)は必ずしも有効にする必要がないという点です。ログイン状態をRedisやJWTに置き、アプリを本当にステートレスにすることが、マルチインスタンス拡張の前提になります。セッション維持を有効にすると、1台が落ちたときにそのマシン上のユーザーはやはり切断されます。

1. 負荷分散が必要なとき、過剰設計になるとき

負荷分散は最初から導入すべきものではありません。日次アクセスが5000以内なら、2コア4GのVPS1台でNginx+PHP+MySQLを動かせば十分で、数百元でLBを買うと複雑さが増すだけです。マルチインスタンスが本当に必要なシグナルは3つあります。単一マシンのCPUが長期的に60%を超える、リリース時に必ず停止が必要、単一障害で問い合わせを失ったことがある。このうち2つに当てはまったら、LBを導入しましょう。

独立サイトの典型的なアップグレード経路は、単一VPSでcomposeを動かす(日次1万以内)→ MySQLを別マシンに分離(日次3万)→ アプリを2台+クラウドLBで動かす(日次5万)→ アプリ3〜5台+自動スケーリング(日次20万以上)です。ステップを飛ばさないでください。CDNはLBより先に静的トラフィックを受け止め、オリジンサーバーの負荷を半分に減らせます。詳しくはCDNグローバル高速化。

フェーズ デプロイ形態 アプリインスタンス数 日次アクセスの目安 月額コスト増分
立ち上げ期 単一VPS+compose 1 1万未満 0
成長期 アプリ1台+DB独立1台 1 1万〜5万 +150元
安定期 アプリ2台+クラウドLB 2 5万〜20万 +LB費用約100元
ピーク時 アプリ3〜5台+自動スケーリング 3至5 20万超 +時間単位の課金

2. L4かL7か:独立サイトはどの層を選ぶか

負荷分散は4層(L4、TCP/IPで転送)と7層(L7、HTTPパスで転送)に分かれます。L4は性能が高く設定も簡単ですが、ポート単位の転送しかできません。L7はドメイン、パス、Headerに基づいてルーティングでき、カナリアリリースやHTTPSオフロードも可能です。独立サイトはL7を選びましょう。パスごとに振り分ける必要があるからです。静的ファイルはCDN、APIはアプリ、管理画面は別のインスタンス群へ。

クラウド各社のLB選び:AWSはALB(Application Load Balancer)、Alibaba CloudはSLBまたはALB、Tencent CloudはCLB。機能は重なり合い、料金は月100〜200元から。判断基準はひとつ。要件が「2台のマシンを順番に回す」だけなら最安のL4 LBを選ぶ。パスによるルーティング、カナリアリリース、ドメイン別の振り分けが必要ならL7 LBを選ぶ。

比較項目 L4 TCPロードバランシング L7 HTTPロードバランシング
振り分けの基準 IP+ポート ドメイン/パス/Header/Cookie
性能 非常に高い、マイクロ秒級 やや低い、ミリ秒級
HTTPSのオフロード 非対応 対応、証明書はLBに配置
カナリアリリース トラフィック比率では不可 重み付けでトラフィックを切替可能
独立サイトでの適用 シンプルな2台の順番回し マルチパスルーティング、カナリア
月額の目安 約80〜120元 約150〜250元

三、ヘルスチェック:誤検知で切り離さないための設定

ヘルスチェックはLBの要です。緩すぎると落ちたマシンがトラフィックを受け続け、厳しすぎると起動が少し遅いだけで誤って切り離され、雪崩を引き起こします。独立サイトの標準設定は、チェックパスを/health(200のみ返し、DBは見ない。DBの遅延をLBに伝染させないため)、間隔10秒、3回連続失敗で切り離し、2回連続成功で復帰です。

/healthは軽量でなければなりません。よくある誤りはMySQL接続を1回確認させることで、DBが揺らぐと全アプリインスタンスがLBから外れ、サイト全体が503になります。正しい方法は、/healthはプロセスの生存状態だけを返し、DBの健全性は独立した/health/dbで確認し、監視のみで切り離しの判断には使わないことです。監視アラートのしきい値は次を参照サイト監視とアラート。

パラメータ 推奨値 説明 よくある誤り
チェックパス GET /health DBを見ず200のみ返す DBを見て全台切り離し
チェック間隔 10秒 感度と誤検知のバランス 1秒は攻めすぎ
タイムアウト 5秒 超えると1回失敗 1秒は短すぎ
不健全のしきい値 3回連続失敗 ノードを切り離し 1回失敗で切り離し
健全なしきい値 2回連続成功 復帰キュー 1回成功で復帰
レスポンスコード 200は健全 その他は失敗 503を健全扱い

四、セッション維持:できるだけオフにする

多くの人が初めてマルチインスタンスを組むとき、まず「ユーザーがA機でログインして、次のリクエストがB機に届いたらログアウトするのでは」と考え、セッション維持をオンにします。これは短期は楽でも長期でツケが回るやり方です。セッション維持の問題は、A機が落ちるとA機に張り付いた全ユーザーがログアウトし、フェイルオーバーの意味が半減することです。

正しい方法は、セッションをアプリのメモリから外に出すことです。PHPはRedisにsessionを保存し、NodeはJWTのステートレストークンを使い、ログイン状態をすべて共有ストレージに集約します。こうすればどのアプリインスタンスでもどのユーザーのリクエストを処理でき、どれか1台が落ちてもオンラインユーザーに影響しません。セッション維持をオンにするのは、古いシステムを変えられない、またはサードパーティプラグインがローカルsessionに強く依存している、の2つの場合だけです。

セッション方式 拡張性 障害時の影響 移行コスト 推奨度
ローカルファイルsession 悪い、stickyが必須 1台停止=ユーザーログアウト 低 非推奨
Redisでsessionを一元管理 良い 無停止で切替 中、設定変更で対応 推奨
JWTステートレスtoken 最適 無停止で切替 高、認証の改修が必要 新規プロジェクトに推奨
LB cookieスティッキー 悪い例 固定されたマシンが落ちると切断 低、スイッチを入れるだけ 一時的な移行のみ

五、フェイルオーバー:LBが本当に切り替わるか検証する方法

LBを設定しただけではフェイルオーバーは機能しません。多くのチームは稼働後に一度もマシンを止めてみないまま、本当に落ちて初めてLBにヘルスチェックが設定されていない、セキュリティグループが開放されていないと気づきます。稼働前に必ず一度、能動的な障害訓練を行ってください。本番環境(またはステージング)でアプリAを手動で停止し、LBが30秒以内にトラフィックをBへ切り替えるか、ユーザーのリクエストが違和感なく処理されるかを確認します。

もう一つのよくある落とし穴は、2台のアプリインスタンスが同じ物理マシンや同じ電源ラックにあることです。ラック全体の停電で2台とも落ちます。少なくとも2つのアベイラビリティゾーン(AZ)にまたがって配置するか、最低でも2台の異なるホストに分けてください。バックアップと復旧訓練の完全な方法論はこちらサイトのバックアップと復元演習。

事例:あるB2Bサイトは当初1台のVPSでWordPressを運用していました。ある未明にホストのメンテナンスで停電し、サイトが4時間ダウン、その間にヨーロッパの顧客からの問い合わせを3件逃しました。その後、2台目のアプリインスタンスをクラウドLBに接続し、sessionをRedisに移し、アベイラビリティゾーンをまたいで配置しました。次のメンテナンス時間には、インスタンスBが自動的に全トラフィックを引き継ぎ、顧客も営業も気づきませんでした。月300元のインスタンス費用は、一度のダウンで失う問い合わせの価値よりはるかに安いのです。

訓練シナリオ 操作 期待結果 基準を満たさない場合の対応
アプリプロセスを停止 systemctl stop app 30秒以内にLBが切り離し、トラフィックをBへ ヘルスチェックパスを確認
アプリのネットワークを遮断 iptablesでポートをブロック 10秒以内に切り離し セキュリティグループでLBの網段を開放しているか確認
マシンを再起動 reboot 起動後に自動でキューへ復帰 起動スクリプトとhealthを確認
データベースの揺らぎ スロークエリを注入 アプリが誤って切り離されない healthでDBを確認してはいけない
全トラフィックをBへ 重みをBに100設定 Bが単独で5分間耐える Bの処理能力を負荷テスト

FAQ よくある質問

1日の訪問数がいくつならロードバランサーが必要?
絶対的な数字はありませんが、3つのシグナルのうち2つが出たら導入すべきです。単台の4コア8GでCPUが長期間60%超、リリース時に必ず停止が必要、単機故障で問い合わせを逃したことがある。独立サイトの現実は、1日5万訪問以内なら単台マシンとCDNで十分です。まずCDNを設定し静的リソースを分離すれば、オリジンの負荷は半分に減り、多くの場合マルチインスタンスは不要です。
セッション維持は結局必要か?
デフォルトでは不要です。sessionをRedisに移すかJWTに変更し、アプリをステートレスにすれば、どのインスタンスでもどのリクエストも処理でき、単機故障でもユーザーは気づきません。sticky sessionを有効にすると、落ちたマシン上のユーザーは全員切断され、フェイルオーバーが無意味になります。古いシステムでローカルsession依存がどうしても変えられない場合のみ、cookieスティッキーを一時的に有効にして移行します。
ヘルスチェックでデータベースを確認してはいけないのはなぜ?
データベースの揺らぎはLBにも伝染します。/healthでMySQLを1回照会し、スロークエリが5秒を超えると、LBはこのアプリを異常と判定します。全アプリインスタンスが同時にDBへ照会すれば、同時に異常判定され、サイト全体が503になります。正しいやり方は、/healthはプロセスの生存だけを返し、DBの健全性は独立した監視メトリクスで見て、LBの切り離し判断には関与させないことです。
2台のインスタンスを同じ物理マシンに置いてもいいですか?
ダメです。フェイルオーバーをしていないのと同じです。同じ物理マシンの電源断やハイパーバイザの障害で、2台とも落ちます。少なくとも2つのアベイラビリティゾーン(AZ)をまたぐか、最低でも2台の異なるホストマシンに分けてください。クラウド事業者は通常、インスタンス作成時に異なる物理マシンへ配置するポリシーを指定できます。予算的に2台しか買えないなら、別々のAZを選びましょう。
クラウド事業者のLBの月額はいくらですか?
L4で月80〜120元程度、L7で月150〜250元程度、別途トラフィック課金が1GBあたり約0.5元です。独立系サイトの月間トラフィックは通常数百GBなので、LB費用は合計200元以内に収まります。AWS ALBはやや高く、基本料が月約20ドル+トラフィック費です。予算が厳しければNginxで自前のLBを組めば月額コストは浮きますが、高可用性は自分で維持する必要があります。
フェイルオーバーが本当に機能しているか、どう確認しますか?
リリース前に一度、能動的な演習をします。ステージングか本番の閑散時間帯に、手動でアプリAのプロセスをstopし、curlでLBを打ち続け、リクエストが30秒以内にエラーなくBへ切り替わるか観察します。さらにマシン再起動後に自動でプールへ復帰するかもテストします。演習に通らなければリリースしないでください。実際の障害時に30秒のトラブルシュート時間など誰も与えてくれません。

最後に

独立系サイトにとってのロードバランサーの価値は、半分はトラフィックをさばくこと、もう半分は障害をさばくことです。前者は多くの人が計算できますが、後者は見落とされがちです。アプリインスタンスを1台増やすコストで、「1台落ちてもユーザーは気づかない」状態を買える。これはB2Bの問い合わせ獲得の場面では、そのままお金になります。

実装は3ステップ。まずアプリをステートレス化し、セッションをRedisへ移します。次に2台目のインスタンスを立ち上げ、クラウドLBの背後にぶら下げ、ヘルスチェックを設定します。最後にプロセスをkillする演習を1回行い、30秒以内にトラフィックが切り替わることを確認します。この3ステップを終えて、初めてマルチインスタンス構成が実用になります。関連する監視アラートはサイト監視とアラート、自動スケーリングの応用は自動スケーリング。

覚えておきたい一言。ロードバランサーの意味は負荷分散ではなく、どのマシンが落ちてもユーザーも問い合わせも気づかないようにすることです。

环形山
环形山 クレーター専門家

公式アカウント · 環形山 Crater

環形山(Crater)は、WordPress独立サイト開発+Google SEO+GEO全域成長に特化した海外展開支援会社で、スマートハードウェア、産業機器、SaaS、新エネルギーなどの分野を手がけています。

プロダクト能力方法論ホワイトペーパー業界レポート
965件のシェア
78件のナレッジベース