CentOS 7 の yum でさくっとインストールできるバージョンで試しています。
- haproxy-1.5.14-3.el7.x86_64
appsession
アプリケーションが発行する cookie の値とサーバとの対応表のテーブルを HAProxy が保持する。
appsession PHPSESSID len 32 timeout 30m request-learn
この例だと PHPSESSID
という名前のクッキーの値の先頭 32 バイトを用いてテーブルを作成する。有効期限は 30 分で有効期限が切れるとテーブルから削除される。
request-learn
を付けると、HAProxy はリクエストの Cookie からもテーブルに追加する。request-learn
がない場合、次のようなケースで問題になる。
- サイトにアクセス
- クライアントの Cookie なし
- HAProxy は Cookie の値が対応表にないのでランダムに振り分ける
- サーバが Set-Cookie を返す
- HAProxy が Cookie の値を記録する
- クライアントの Cookie なし
- サイトにアクセス
- クライアントが Cookie を送る
- HAProxy が Cookie の値で対応表を引いて振り分けるサーバを決定する
- サーバは Cookie を発行済みなので Set-Cookie を送らない
- クライアントが Cookie を送る
- HAProxy を再起動する
- サイトにアクセス
- クライアントが Cookie を送る
- HAProxy は Cookie の値が対応表にないのでランダムに振り分ける
- サーバは Cookie を発行済みなので Set-Cookie を送らない
- クライアントが Cookie を送る
- サイトにアクセス
- クライアントが Cookie を送る
- HAProxy は Cookie の値が対応表にないのでランダムに振り分ける
- サーバは Cookie を発行済みなので Set-Cookie を送らない
- クライアントが Cookie を送る
PHP のセッションはクライアントが Cookie を送るとサーバは Set-Cookie を送らないので (session_regenerate_id
とかしなければ) 、request-learn
を指定しておくと無難。
prefix
と mode
も指定できるけどあんまり使わなさそう。
この方法は対応表のテーブルを保持するために HAProxy でメモリを消費する。
ボットとか死活監視とかのセッションの必要がないリクエストは ignore-persist
で除外しておけば、それらのリクエストによって appsession のテーブルが大きくなることを防止できる。
appsession PHPSESSID len 64 timeout 30m request-learn acl ab hdr_sub(User-Agent) -i ApacheBench ignore-persist if ab
cookie insert
HAProxy 自身が Cookie を発行する。
cookie HAPROXY insert nocache indirect preserve httponly secure maxidle 30m maxlife 8h server ap01 192.168.33.21:80 check cookie ap01 server ap02 192.168.33.22:80 check cookie ap02
この例だと HAPROXY=ap01
のような Cookie が発行される。
nocache
を指定すると、レスポンスヘッダに Cache-control: private
を追加することでプロキシサーバがキャッシュしないようにする。スティッキーのための Cookie をプロキシに覚えさせるわけにはいかないので、nocache
かもしくは後述の postonly
を指定しておくのが無難。
indirect
を指定すると、クライアントが送信した Cookie (上の例だと HAPROXY=ap01
) は HAProxy が削除するので、サーバに Cookie の値は渡らない。
preserve
を指定すると、サーバで setcookie('HAPROXY', '', time()-3600)
とかで Cookie 削除のためのレスポンスを返すことができる。逆に、指定していなければ、サーバがそのようなレスポンスを送っても HAProxy が削除する。
httponly
と secure
はそのままの意味、domain
も指定できる。
maxidle 30m
は、指定した時間以上未アクセスだと無効になるように Cookie を発行する。
maxlife 8h
は、Cookie を最初に発行してから指定時間以上経過すると無効になるように Cookie を発行する。
maxidle
や maxlife
は Cookie に HAPROXY=ap01|VwNGp|VwNGl
のようなタイムスタンプに基づく値を付与することで実現される。
postonly
を指定すれば POST リクエストのレスポンスにのみ Set-Cookie
が発行されるようになる。
大抵のアプリではログイン画面の POST リクエストからがセッションの始まりになるので、postonly
を指定しても良いかもしれない。
appsession
とは異なり、Cookie の値から直接振り分け先が導出されるので、対応表のために余分なメモリを消費することはない。
cookie prefix
アプリケーションが発行するクッキーの値の先頭に HAProxy が追記する。
cookie PHPSESSID prefix server ap01 192.168.33.21:80 check cookie ap01 server ap02 192.168.33.22:80 check cookie ap02
この例だと、アプリケーションが PHPSESSID=xyz123
という Cookie を発行したら、HAProxy がそれを PHPSESSID=ap01~xyz123
のように書き換える。
cookie rewrite
prefix とほとんど同じだけど、先頭に追記じゃなくてただの書き換えになる。
cookie HAPROXY rewrite server ap01 192.168.33.21:80 check cookie ap01 server ap02 192.168.33.22:80 check cookie ap02
この例だと、アプリケーションが HAPROXY=hoge
のように Cookie を発行したら、HAProxy がそれを HAPROXY=ap01
のように書き換える。
PHPSESSID
のようなアプリケーションのセッション用 Cookie を指定してしまうと HAProxy がその値を書き換えてしまうので、セッションの維持ができない。