【PHP】大規模システムにおけるPHP複数台APロードバンサー構成でセッションを維持する手法

f:id:kitahashi-ryoichi:20180328232237g:plain

負荷分散 - ロードバランサとは、DNSラウンドロビンとは

今や上記のようなロードバランサでWebサーバを複数台配置して、高可用構成は一般的になっていますよね。PHPが複数台に振り分けられると主にセッション問題が発生します。

 

発生するセッション問題

PHPデフォルトだと/var/lib/php/session以下にセッションキーが作られて、サーバA,B,Cのどこかにファイルが作られてしまいます。$_SESSION動かない!

 

解決法とその考え方

考え方は大きく2つ

  1.  同じ人には同じサーバーを常に見てもらう
  2. サーバー側のセッションファイルを複数台で同期する

 

同じ人には同じサーバーを常に見てもらう

1-1.ロードバランサのパーシステンス設定を「source IP」にする

送信元IPを判断基準にして振り分けるサーバーをロードバランサーに決めてもらう設定。だいたいの企業のインフラではNATルータによるIP変換が入っているのでこの方法が採用できないが一番お手軽。

NATとは

1-2.ロードバランサのパーシステンス設定を「cookie」にする

セッションCookieを発行してブラウザごとに振り分けるサーバーをロードバランサーに決めてもらう設定。Webアプリだと最もよく使われる構成。

オススメ!

 

サーバー側のセッションファイルを複数台で同期する

同期する方は色々手段が多い

  • NFSを使う
  • DBを使う
  • Memcachedを使う
  • rsyncを使う
  • iSCSIを使う

 

現実的なNFS・DB・Memcachedだけに絞って説明していきます。

 

2-1.NFSで3台すべてに1つのディスクをマウントしてセッションファイルを同期する(面倒くさい!すぐ実装するパターン)

なんだか遅くなるっていう記事が多いですが最も簡単。しかし、単一障害点になるためオススメはできない方法。APサーバーは死んでもセッション保管用のディスクは死なないのであれば単一障害は避けられる。

2-2.単一障害点を回避するHA構成のDBにセッションを書き出す(高可用性をとるけど速度ちょっと捨てるパターン)

セッション管理テーブルを作って、セッションキーをDBでごりごり管理してください。排他制御も忘れずに。DBは普通HA構成なので単一障害点になりませんよね。

 

実装方法はこの辺にサンプルがあります

宇大を出たけれど: PHPのsessionをDBに保存する。その壱

 

2-3.DBだと遅いからMemcacedにセッションを書き出す(高可用性はちょっと捨てるけど高速!)

ECのフロントサイトとかでは高可用性の方が重視されてDBが使われますけど、死ぬほどアクセスされるWebサービスとかだとそうもいかなくてmemcachedなんかが採用されると思います。

 

組合せてセッション管理する!

source IP × DB とか cookie × memcachedみたいに人単位にサーバーを割り振って、セッションファイルを同期して1台死んで片肺になってもセッションが維持できるようにしています。

 

まとめ

エンタープライズWebアプリ=cookie × DB

コンシューマWebアプリ=source IP × memcached

こんな感じでいかがでしょう!