mod_proxy_balancer単体でstickysessionを設定
mod_proxy_balancer単体でstickysessionを設定 †
mod_proxy_balancerのみでstickysessionを設定する方法について解説します。
いろいろ調べるといろいろなやり方がありそうですが、Webサーバのmod_proxy_balancerのみでstickysessionまで実現できたので、そのメモ書きです。
想定の構成は以下の通りです。
想定構成は、フロントにWEBサーバ1台、バックにAPサーバ2台です。
Webサーバは何台あっても、上位にロードバランサーがいれば設定は同一となります。
- Webサーバ : mod_proxy_balancerの設定対象です。
- APサーバ : mod_proxy_balancerにて振り分けする対象のAPサーバです。
セッション保持して、振り分けをする必要があるアプリケーションが動作することとします。
mod_proxy_balancerの設定(stickysession無し) †
まず、stickysessionの設定なしのmod_proxy_balancer.confの設定例です。
■mod_proxy_balancer.conf
まず、管理画面の設定。試験環境であれば、許可するセグメントの設定だけして、パスワード認証はオフにしても問題ないかもしれません。
<Location /manager/balancer-manager> SetHandler balancer-manager Order deny,allow Deny from all Allow from XX.XX.X.X/XX ←セグメントを指定(例えば、192.168.0.0/24とか) AuthType Basic AuthName "For balancer-mangager" # AUthUserFile /etc/httpd/conf/balancer_password ←コメントアウト # Require valid-user ←コメントアウト </Location>
次に、実際の振り分けの設定を入れます。
ProxyPass /test balancer://mycluster/ <Proxy balancer://mycluster/> BalancerMember http://app01:80/ timeout=310 retry=3 BalancerMember http://app02:80/ timeout=310 retry=3 </Proxy>
この設定で、バックエンドのAPサーバにラウンドロビンで振り分けができます。
この状態で、webサーバの管理用URL(http://web01/manager/balancer-manager)にアクセスすると、以下のような画面が出力されるはずです。
LoadBalancer Status for balancer://mycluster StickySession Timeout FailoverAttempts Method - 4 1 byrequests Worker URL Route RouteRedir Factor Set Status Elected To From http://app01/ 1 0 Ok 0 0 0 http://app02/ 1 0 Ok 0 0 0
この状態では、Webサーバにアクセスすると、セッションによって振り分けされず、app01とapp02と順番に振り分けされます。
→Electedが順番に増加するはずです。
LoadBalancer Status for balancer://mycluster
StickySession Timeout FailoverAttempts Method - 4 1 byrequests Worker URL Route RouteRedir Factor Set Status Elected To From http://app01/ 1 0 Ok 3 820 304 http://app02/ 1 0 Ok 2 240 801
mod_proxy_balancerの設定(stickysession有り) †
Webサーバのmod_proxy_balancerの設定のみでバックのAPサーバへの振り分けをstickinessにするため、以下のような設定を入れます。
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED ←追加① ProxyPass /test balancer://mycluster/ <Proxy balancer://mycluster/> BalancerMember http://app01:80/ timeout=310 retry=3 route=route01 ←追加② BalancerMember http://app02:80/ timeout=310 retry=3 route=route02 ←追加② ProxySet stickysession=ROUTEID ←追加③ </Proxy>
- 追加①:レスポンスのヘッダーにcookie「ROUTEID」を追加
この構文で、環境変数「BALANCER_ROUTE_CHANGED」が存在する場合、「ROUTEID」に「.%{BALANCER_WORKER_ROUTE}e」を設定し、cookieに追加する。 - 追加②:routeの設定を追加する。
- 追加③:バランサーのstickysession名をROUTEIDに設定する。
追加③は、通常はアプリケーションのセッション名(JSESSIONID や PHPSESSIONID)を指定します。
が、実際はアプリケーションにより設定するセッション名や値が異なるため、アプリケーションごとの設定になり煩雑です。(まあ、アプリケーションによってはアプリケーションごとに真に必要なケースもあると思いますが、、、)
そこで、追加①でBALANCER_WORKER_ROUTEという環境変数を「ROUTEID」設定し、これをcookieに設定することで、この情報をもとに振り分けを実施する設定とします。
この状態で、webサーバの管理用URL(http://web01/manager/balancer-manager)にアクセスすると、以下のような画面が出力されるはずです。
LoadBalancer Status for balancer://mycluster StickySession Timeout FailoverAttempts Method ROUTEID 4 1 byrequests Worker URL Route RouteRedir Factor Set Status Elected To From http://app01/ route01 1 0 Ok 0 0 0 http://app02/ route02 1 0 Ok 0 0 0
画面からも、StickySession?のところに「ROUTEID」が指定されていることがわかります。
参考情報 †
Apacheモジュール:mod_proxy_balancer
上の文書の一部を引用
%{MYCOOKIE}C
The value contained in the cookie with name MYCOOKIE. The name should be the same given in the stickysession attribute.
%{Set-Cookie}o
This logs any cookie set by the back-end. You can track, whether the back-end sets the session cookie you expect, and to which value it is set.
%{BALANCER_SESSION_STICKY}e
The name of the cookie or request parameter used to lookup the routing information.
%{BALANCER_SESSION_ROUTE}e
The route information found in the request.
%{BALANCER_WORKER_ROUTE}e
The route of the worker chosen.
%{BALANCER_ROUTE_CHANGED}e
Set to 1 if the route in the request is different from the route of the worker, i.e. the request couldn't be handled sticky.
- 環境変数「BALANCER_ROUTE_CHANGED」は、ルートが変わった時に1になります。
- つまり、前述の追加①では、ルートが変わった(新しく設定された時も含む)場合にenv=BALANCER_ROUTE_CHANGEDが真となり、cookieに"ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/"が設定される。
というわけです。
Apacheモジュール:mod_headers
上の文書より、追加①の「Header add・・・」は、バックエンドのAPサーバから処理が実行されたのちに動作することがわかります。
→PHPアプリケーションの処理が終わって、フロントWebサーバのApacheにリクエストが返却され、クライアントに返却する前のタイミングで、cookieを追加します。
動作確認のためのログ設定 †
LogFormat?の出力に以下の3つを追加します。
- %{BALANCER_WORKER_ROUTE}e : バックエンドのAPサーバに指定したroute ※追加②で追加した内容
- %{BALANCER_ROUTE_CHANGED}e : BALANCER_ROUTE_CHANGEDの値。真の場合は「1」、変更が無い場合は「-」で出力
- %{ROUTEID}C : cookieの「ROUTEID」の内容
例えば、以下の通りに設定します。
■httpd.conf
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %{BALANCER_WORKER_ROUTE}e %{BALANCER_ROUTE_CHANGED}e %{ROUTEID}C" combined
これで、振り分けの状況がログから見えるようになります。
動作確認 †
まず、最初にアクセスした際のWebサーバのアクセスログはこんな感じで出力されます。
※最後の3つの要素のみ記載
10.XX.XX.XX - - *** route01 1 - ↑① ↑②↑③
- ③:%{ROUTEID}Cが「-」であり、今回のリクエストのcookieには「ROUTEID」がなかったことを示します。
- ②:%{BALANCER_ROUTE_CHANGED}eが「1」であり、これは今回ルートが変更された(新しく振られた)ことを示します。
- ①:%{BALANCER_WORKER_ROUTE}eが「route01」であり、「route01」が選択されたことを示します。
もう一回同じブラウザからアクセスすると以下の通りの出力になります。
10.XX.XX.XX - - *** route01 - .route01 ↑① ↑②↑③
- ③:%{ROUTEID}Cが「.route01」であり、今回のリクエストのcookieの「ROUTEID」に「.route01」が設定された状態でリクエストが送信されたことを示します。
- ②:%{BALANCER_ROUTE_CHANGED}eが「-」であり、これは今回ルートが変更されなかったことを示します。
- ①:%{BALANCER_WORKER_ROUTE}eが「route01」であり、前回のアクセスから変更がなかったことがわかります。
この結果、ルートが「ROUTEID」により保持された(Stickinessとなった)ことがわかります!
まあ、この他に、バックエンドのAPサーバのアクセスログを確認することも重要です。※本記事では割愛しますw
参考にしたサイト †
apache公式サイト(英) Apache Module mod_proxy_balancer
apache公式サイト(英/日) Apache Module mod_proxy
- http://httpd.apache.org/docs/trunk/en/mod/mod_proxy.html
- http://httpd.apache.org/docs/trunk/ja/mod/mod_proxy.html
apache公式サイト(日) Apache モジュール mod_headers
apache公式サイト(日) Apache モジュール mod_setenvif
apache公式サイト(日) Apache モジュール mod_log_config
以下は参考にしたブログサイトです。
HTTP Header Fields
HTTP Cokies
†
Apache Proxy Balancer上でSet-Cookieするには
mod_proxy_balancer の stickysession について
mod_proxy_balancerの設定、特にstickysessionについて