ロードバランサ配下のPHPセッションをmemcachedで共有する方法

ネットワーク # サーバー運用 # ロードバランサ

こんにちは、UOZUです!

先にエンハンスドロードバランサのセッション維持機能について記事を書きましたが、今回はセッション維持機能の無いロードバランサのPHPセッションをmemcachedで共通化してみようと思います。

PHPセッションの管理サンプル

PHPセッションでは、ブラウザ側のCookieにセッションIDを持たせ、サーバー側に保存されたセッション情報と照合することで、同じ利用者の状態を管理します。

デフォルトではセッション情報は各サーバーのローカルディスクに保存されるため、ロードバランサ配下で接続先サーバーが切り替わると、セッション情報を正しく参照できない場合があります。

サンプルコードを作って試してみます。

[root@uozu-lb1 ~]# vi /var/www/html/session.php
<?php
session_name("php_uozu");
session_start();
if (isset($_SESSION['count'])) {
    $_SESSION['count']++;
} else {
    $_SESSION['count'] = 1;
}
?>
<?php echo gethostname(),"\n", $_SESSION['count'], "\n" ; ?>

「php_uozu」でセッション情報を管理し、すでにブラウザにセッションCookieがある場合、ホスト名の下の数字が増える単純なスクリプトです。

[root@uozu-lb1 ~]# curl http://localhost/session.php
uozu-lb1
1

[root@uozu-lb1 ~]# curl http://localhost/session.php
uozu-lb1
1
[root@uozu-lb1 ~]# curl -c cookie.txt -b cookie.txt http://localhost/session.php
uozu-lb1
1

[root@uozu-lb1 ~]# curl -c cookie.txt -b cookie.txt http://localhost/session.php
uozu-lb1
2

また、ブラウザ上のCookieの情報と、サーバ内のセッション情報は同じ名前で保存され、アクセスの際に突合されるという仕組みになっています。

[root@uozu-lb1 ~]# cat cookie.txt
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.

localhost       FALSE   /       FALSE   0       php_uozu        ar8ejnsnknl66vikfbtv66lhee
[root@uozu-lb1 ~]# ll -t /var/lib/php/session/
total 12
-rw------- 1 apache apache 10 Aug  9 21:27 sess_ar8ejnsnknl66vikfbtv66lhee
-rw------- 1 apache apache 10 Aug  9 21:27 sess_mo3peefa8jf2unhh14o6poa1mk
-rw------- 1 apache apache 10 Aug  9 21:27 sess_ge4mfdmdcc6lso1eiogap0lfq1

[root@uozu-lb1 ~]# cat /var/lib/php/session/sess_ar8ejnsnknl66vikfbtv66lhee
count|i:2;

ロードバランサ利用の際の問題

ロードバランサを利用した際、ロードバランサ自身にセッション維持機能は無く、常に振り分けアルゴリズムはleast connection(変更不可)となる為、アクセス後にどのサーバーにつながるかは保証されておらず、正しくPHPセッションが利用できなくなります。

$ curl -c cookie.txt -b cookie.txt http://203.0.113.130/session.php
uozu-lb1
1

$ curl -c cookie.txt -b cookie.txt http://203.0.113.130/session.php
uozu-lb2
1

$ curl -c cookie.txt -b cookie.txt http://203.0.113.130/session.php
uozu-lb1
2

$ curl -c cookie.txt -b cookie.txt http://203.0.113.130/session.php
uozu-lb2
2

memcachedとPHPの設定変更

サーバ内のPHPセッションの保存方法(session.save_handler)ですが、デフォルトではfilesとなっているので、サーバのローカルディスクに追記されていきます。

[root@uozu-lb1 ~]# less /etc/php-fpm.d/www.conf

php_value[session.save_handler] = files
php_value[session.save_path]    = /var/lib/php/session

memcachedを導入し、このセッション情報の保存先を変更していきます。

今回は検証のため 0.0.0.0 で待ち受けていますが、待ち受けIPはプライベート側のIPアドレスに限定し、パケットフィルターやOSのファイアウォールでWebサーバー間の通信だけを許可する構成をおすすめします。

[root@uozu-lb1 ~]# dnf install memcached php-pecl-memcached

[root@uozu-lb1 ~]# cat /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 127.0.0.1,::1"

[root@uozu-lb1 ~]# vi /etc/sysconfig/memcached
[root@uozu-lb1 ~]# cat /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 0.0.0.0,::"


[root@uozu-lb1 ~]# systemctl enable --now memcached

[root@uozu-lb1 ~]# ss -tnl
State          Recv-Q          Send-Q                   Local Address:Port                    Peer Address:Port
LISTEN         0               1024                           0.0.0.0:11211                        0.0.0.0:*
LISTEN         0               128                            0.0.0.0:22                           0.0.0.0:*
LISTEN         0               1024                              [::]:11211                           [::]:*
LISTEN         0               511                                  *:80                                 *:*
LISTEN         0               128                               [::]:22                              [::]:*
[root@uozu-lb1 ~]# vi /etc/php-fpm.d/www.conf

php_value[session.save_handler] = memcached
php_value[session.save_path]    = "localhost:11211,203.0.113.132:11211"

[root@uozu-lb1 ~]# php-fpm -t
[09-Aug-2026 21:44:24] NOTICE: configuration file /etc/php-fpm.conf test is successful

[root@uozu-lb1 ~]# systemctl restart php-fpm

また、同様の作業は他のサーバーでも行います。

memcached設定後の動作確認

設定変更後、改めてcurlでロードバランサからPHPセッションの管理サンプルにアクセスをしてみます。

$ curl -c cookie.txt -b cookie.txt http://203.0.113.130/session.php
uozu-lb1
1

$ curl -c cookie.txt -b cookie.txt http://203.0.113.130/session.php
uozu-lb2
2

$ curl -c cookie.txt -b cookie.txt http://203.0.113.130/session.php
uozu-lb1
3

$ curl -c cookie.txt -b cookie.txt http://203.0.113.130/session.php
uozu-lb2
4

$ curl -c cookie.txt -b cookie.txt http://203.0.113.130/session.php
uozu-lb1
5

無事、サーバ間でPHPセッションの共通化が出来ました。

$ cat cookie.txt
# Netscape HTTP Cookie File
# https://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.

133.125.230.181 FALSE   /       FALSE   0       php_uozu        3peamno9nun1ftu3o7k1po66sg

memcachedの中にもセッション情報が入っていることが確認できますね。

[root@uozu-lb1 ~]# memcached-tool localhost:11211
  #  Item_Size  Max_age   Pages   Count   Full?  Evicted Evict_Time OOM
  2     120B       240s       1       1      no        0        0    0

[root@uozu-lb1 ~]# echo 'stats cachedump 2 1' | nc localhost 11211
ITEM memc.sess.key.3peamno9nun1ftu3o7k1po66sg [10 b; 1786281655 s]
END

[root@uozu-lb1 ~]# echo 'get memc.sess.key.3peamno9nun1ftu3o7k1po66sg' | nc localhost 11211
VALUE memc.sess.key.3peamno9nun1ftu3o7k1po66sg 0 10
count|i:5;
END

ただし、memcachedを利用したセッションは、memcachedやサーバが再起動してしまうと消えてしまうため注意が必要です。

さいごに

今回は、ロードバランサ配下でPHPセッションを利用する際の問題と、memcachedを使ってセッション情報を共通化する方法を確認しました。

PHPのデフォルト設定では、セッション情報は各サーバーのローカルディスクに保存されます。そのため、ロードバランサによって接続先サーバーが切り替わると、同じセッションIDを持っていても、別サーバー側ではセッション情報を参照できない場合があります。

session.save_handlermemcached に変更し、複数サーバーから同じセッション保存先を参照できるようにすることで、接続先サーバーが切り替わってもPHPセッションを継続できることを確認できました。

ただし、memcachedに保存したセッション情報は、memcachedやサーバーの再起動で消える可能性があります。また、memcachedを外部から接続できる状態にすると危険なため、待ち受けIPやファイアウォール設定には注意が必要です。

状態セッション保存先ロードバランサ配下での挙動
デフォルト設定各サーバーのローカルディスク接続先サーバーが変わるとセッション情報を共有できない
memcached設定後memcached接続先サーバーが変わってもセッション情報を参照できる
memcached再起動後消失する可能性ありセッションが消えるため注意が必要
永続化したい場合NFSなどの共有ストレージも候補性能・ロック・障害影響を考慮する必要あり

ロードバランサ配下でPHPアプリケーションを動かす場合は、セッション情報をどこに保存するかを事前に設計しておくことをおすすめします。

最後までお読みいただき、ありがとうございます!

この記事を書いた人

UOZU

ネットアシスト運用チーム10年目の運用エンジニア

さくらのクラウド検定 ベーシック

さくらのクラウド検定 アドバンスド

AWS Certified Solutions Architect - Associate