読者です 読者をやめる 読者になる 読者になる

たごもりすメモ

コードとかその他の話とか。

Apacheで勝手にrouteを付加する方法

Apache/mod_proxy

バックエンドワーカー側でStickySessionにrouteを付加できない、もしくは望みのrouteにできない場合、Apache側で勝手に適当なCookieをセットしてやることで、同一リクエストを同一ワーカーに振り分け続けることができる。はず。

ということでやってみた。使用しているのは例によってApache/trunk(2.3)だが、2.2.4でもいけるはず。mod_proxy_balancerに加えて、mod_setenvifとmod_headersが必要。

設定の意図は以下の通り。

  • リクエストにRSESSIONが無い場合
    • レスポンスに、適当なID+ワーカー名を値としたCookie "RSESSION" をセットする
    • このキー名はアプリ側で取り扱っているStickySession名とは異なったものにしておく
  • リクエストにRSESSIONがある場合
    • RSESSIONに含まれるワーカーに配送されること
    • レスポンスはそのRSESSIONの値をそのままセットしなおす

(設定例を7/18に微修正)

 SetEnvIf  ^Cookie$ "RSESSION=([^ ;]*)." R_UNIQUE_ID=$1
 Header    append Set-Cookie "RSESSION=%{UNIQUE_ID}e.%{BALANCER_WORKER_ROUTE}e; path=/" env=!R_UNIQUE_ID
 Header    append Set-Cookie "RSESSION=%{R_UNIQUE_ID}e; path=/" env=R_UNIQUE_ID

 ProxyPass /path1/ balancer://testcluster1/ stickysession=RSESSION
 <Proxy balancer://testcluster1>
     BalancerMember  http://worker1  loadfactor=10  route=worker1
     BalancerMember  http://worker2  loadfactor=10  route=worker2
 </Proxy>

環境変数はそれぞれ、BALANCER_WORKER_ROUTE は配送先ワーカー、UNIQUE_ID はApacheが生成するユニークなID。R_UNIQUE_IDはリクエスト中のセッションIDを格納するのに名付けた。

以上の設定で、意図した通りの動作になってそう。タイムアウトとかは処理できないが、まあ仕方あるまい。

本当は「JSESSIONIDは存在するがrouteがセットされていない場合に、レスポンスのJSESSIONIDにはrouteを付加し、リクエストでJSESSIONIDが渡ってきたらrouteを削ってから望みのworkerに渡してやる」ということをやりたかった。
が、RequestHeaderディレクティブを使ってCookieからrouteを削る設定をすると、routeが無くなった状態でバランサーに渡される -> routeが無いので適当なワーカーに配送される というようになってしまい、望みの動作(配送されるワーカーを固定する)が得られないので断念。

事実上は配送先認識にJSESSIONIDが使われていようとRSESSIONが使われていようとどうでもいいだろうから、特に支障はなさそう。(実際、BIG-IPなんかも勝手に名付けた値を配送先特定に使用しているし。)