複数台WEBサーバのラウンドロビンをサブドメインで固定振り分け

負荷分散構成で、通常はWEBサーバをLBでラウンドロビンさせているけど、特定の操作のあいだはずっと同じサーバに振り分けたいというニーズは、ままあるかと思います。
例えば課金処理のセッションの開始から終了までとか、XSS対策でワンタイムトークンの突き合わせをおこなうとか。
同じIPであれば、L4のLBでもIPのセッション維持で片側に倒すことはできますが、スマホの移動中やテザリングなど、途中でIPが変わる場合は対応できません。
かといってL7のLBでクエリから接続するサーバを振り分けるにも、L7は高いので、予算的に難しいことも多いと思います。
ここでは、Apacheのmod_proxyを使って、サブドメインによって接続するサーバを切り替える、という方法を書きとめておきます。
アプリケーション層から制御できるため、柔軟で、しかも費用がかかりません。
環境:
CentOS 6.5
Apache 2.2.7
構成:
WEBサーバ1 web1 (192.168.1.11)
WEBサーバ2 web2 (192.168.1.12)
ルール:
ドメイン test.com(サブドメインなし) 宛 => web1かweb2のいずれか
ドメイン www1.test.com宛 => web1
ドメイン www2.test.com宛 => web2
イメージ:
Image_2
設定:
@web1

vi /etc/hosts
192.168.1.12 web2 www2.test.com
vi /etc/httpd/conf/httpd.conf
<VirtualHost 192.168.1.11:80>
(略)
<IfModule mod_rewrite.c>
#プライベートネットワーク以外からのアクセスでwww2.test.com宛の接続はweb2へ
RewriteCond %{REMOTE_ADDR} !^192\.168\.1\.\d+$
RewriteCond %{HTTP_HOST} ^www2\.test\.com$
RewriteRule ^(.+)        %{HTTP_HOST}$1 [C]
RewriteRule ^www2\.test\.com(.*) http://www2.test.com$1$2 [P,L]
</IfModule>
</VirtualHost>

@web2

vi /etc/hosts
192.168.1.11 web1 www1.test.com
vi /etc/httpd/conf/httpd.conf
<VirtualHost 192.168.1.12:80>
(略)
<IfModule mod_rewrite.c>
#プライベートネットワーク以外からのアクセスでwww1.test.com宛の接続はweb1へ
RewriteCond %{REMOTE_ADDR} !^192\.168\.1\.\d+$
RewriteCond %{HTTP_HOST} ^www1\.test\.com$
RewriteRule ^(.+)        %{HTTP_HOST}$1 [C]
RewriteRule ^www1\.test\.com(.*) http://www1.test.com$1$2 [P,L]
</IfModule>
</VirtualHost>

これで、www1.test.comへのアクセスは常にweb1へ、www2.test.comへのアクセスは常にweb2へ、サブドメイン指定なしのtest.comはラウンドロビン、になります。
デメリットとしては、LBではなくWEBサーバが振り分けるため、リダイレクトによるネットワークコストがかかります。
また、未検証ですが、LB側で重み付けやIPでセッション維持をおこなっていると、LBはweb1へ振り続け、WEBサーバはweb2に振り続け、といったリダイレクトのループが発生してしまうかもしれません。