前回のPostgresに続きまして、実際に弊社のサービスで利用しているWebサーバーの
ご紹介させていただきます。
Linux+Apacheの標準的な構成で、負荷分散と可用性維持のためにApacheの標準モジュールであるmod_proxy_balancerを利用したロードバランサーを導入しています。
上記の構成にした理由は、以下の3つです。
1.複数のFQDN環境でのSSL提供が可能である
2.拡張性や自由度がある
3.上記の2つを実現させ、低コストでの運用できる
1.複数のFQDN環境でのSSL提供が可能である
弊社のサービスでは、個人情報やクレジットカード情報を取り扱う場合があるため
SSLの利用が必須となっています。
お客様には、共有ドメインのご利用か専用ドメイン(お客様が希望されたFQDN)のどちらかを選択いただきます。
現在、運用している専用ドメインは、100個以上ありますが、
この全ドメインを1つのLinuxサーバで稼働しています。
サービスの設計当初から、お客様が専用ドメインを利用することは必須事項の1つでした。
しかし、SSLを利用する場合に問題になるのが、
1つのSSL(FQDN)に対して、1つのグローバルIPアドレスが必要ということです。
そのため、100ドメイン運用するためには100グローバルIPアドレスが必要となります。
SNI(Server Name Indication)など、SSLハンドシェイク前にホスト名を通知する仕組みが
ありますが、利用できるブラウザが限定されIE6など3から4年前に主流だったブラウザ
からは利用できなくなると判断し採用しませんでした。
また、ハードウェアのロードバランサーを検討しましたが
上記の運用方法に合う機器が当時は非常に高価だったため採用を見送っています。
上記の問題をシンプルに解決するために現在も運用しているのが
Linux Karnelの仮想インタフェイスとApacheのIPアドレスベースのVirtual Hostの組み合わせです。
現在は、1サーバでグローバルIPアドレスを64個運用し、そのサーバを2台運用しています。
※ ↑のサーバもfujyaが仮想化したOpenVZのサーバなので物理サーバは1台です。
IPv4の枯渇問題があるので実際の確保は難しくなっていますが、
この仮想サーバを追加することで専用ドメインの運用を拡張できるようにしています。
2.拡張性や自由度がある
Apacheを選択したのはモジュールによる拡張性があることも1つの理由です。
その1つが今回のテーマにしているmod_proxy_balancerです。
http://httpd.apache.org/docs/2.2/ja/mod/mod_proxy_balancer.html
ご存じの方が多いとは思うので、設定方法などのご説明は省略させていただきますが
弊社では下記のような使い方をしています。
ApacheのIPアドレスごと(FQDNごと)の設定例
<VirtualHost XXX.XXX.XXX.XXX:443> ServerAdmin serveradmin@shanon.co.jp DocumentRoot /var/www/html/ SSLEngine on SSLCertificateFile /etc/httpd/conf.d/ssl-file/sample.crt SSLCertificateKeyFile /etc/httpd/conf.d/ssl-file/sample.nopass.key SSLProtocol -ALL +SSLv3 +TLSv1 -SSLv2 ErrorLog /var/log/httpd/ssl-error_log CustomLog /var/log/httpd/-ssl-access_log combined RewriteEngine On RewriteLogLevel 1 RewriteLog /var/log/httpd/ssl-rewrite_log RewriteCond %{REQUEST_FILENAME} ^/application-A/ RewriteRule ^/(.*) balancer://application-A/$1 [P] RewriteCond %{REQUEST_FILENAME} ^/application-B/ RewriteRule ^/(.*) balancer://application-B/$1 [P] RewriteCond %{REQUEST_FILENAME} ^/application-B/ RewriteRule ^/(.*) balancer://application-B/$1 [P] </VirtualHost>
mod_proxy_balancer(00balancer.conf)のグループの例
<Proxy balancer://balancer-groupA> BalancerMember http://ap-server1:8080 loadfactor=10 BalancerMember http://ap-server2:8080 loadfactor=10 BalancerMember http://ap-server3:8080 loadfactor=20 BalancerMember http://ap-server4:8080 loadfactor=20 </Proxy><Proxy balancer://balancer-groupB> BalancerMember http://ap-server1:8081 loadfactor=10 BalancerMember http://ap-server2:8081 loadfactor=10 BalancerMember http://ap-server3:8081 loadfactor=20 BalancerMember http://ap-server4:8081 loadfactor=20 </Proxy> <Proxy balancer://balancer-groupC> BalancerMember http://ap-server1:8081 loadfactor=10 BalancerMember http://ap-server2:8081 loadfactor=10 BalancerMember http://ap-server3:8081 loadfactor=20 BalancerMember http://ap-server4:8081 loadfactor=20 </Proxy>
バランシンググループ数で35個運用しています。
【mod_proxy_balancerの機能を独自ツールで補強して利用】
mod_proxy_balancerは、複雑な分散アルゴリズムがありませんが
重み付けを考慮した上で、リクエスト数、またはバイト数での分散を行う事ができます。
また、管理画面(balancer-manager)を利用する事で
特定のワーカーをサービスから切り離すことも可能です。
【事前に切り離した上で、アプリケーションを再起動(メンテナンス)したい】
これは、弊社のアプリケーションがApacheの子プロセスとして実行されるFastCGIを利用していることにも原因がありますが、アプリケーションの起動が終わる前にApacheは起動してしまいます。
この間もApacheは処理待ちのリクエストを受けてしまうため、そのサーバに割り当てられた
リクエストのレスポンスタイムは大きく遅延してしまいます。
また、複数のアプリケーションが同じサーバで稼働している場合もあるため
多くのバランサーグループからDisableにするというケースもあります。
そこで、自社で制作したのが管理画面(balancer-manager)をmechanizeで操作し
一括してDisable、Enableにするツールです。
これを監視ツールやメンテナンスツールに組み込み、障害時やメンテナンス時に自動で
バランシングから切り離されるようにしています。
社内用で使っているツールですが、お役に立ちそうでしたらご利用ください。
https://github.com/Shanon/mod_proxy_balancer_tools
(※ 自己責任での利用をお願い致します)
$ ./bl_changer.pl --help
<ex> ./bl_changer.pl --config ./00balancer.conf --domain LBMAN-hostname --group proxy-groupname --range 1-8 --disable
<ex> ./bl_changer.pl --domain LBMAN-hostname --myself --disable
<ex> ./bl_changer.pl --domain LBMAN-hostname --hostname ap-server-hostname --disable
--config -c set 00balancer.conf
--domain -d set LBMAN domain or IP address
--group -g set balancer group name
--force -f if an existing destination
--none-ssl use http request
--disable set disable status
--enable set enable status
--range -r set target serial number for host ex:(1-8)
--myself -m set target my hostname, change all grop (ex `hostname`)
--hostname -H set target hostname , change all group (ex --hostname ap-server-hostname)
--help display help message
このようなオプションを用意しています。
-------------------------------------------------------------
**注意**
ワーカーのホスト名が、
・ap-server1
・ap-server2
の様にホスト名+数字であることを前提にしているツールです。
-------------------------------------------------------------
mechanizeを利用しているため管理画面のGETパラメータが変わると利用できなってしまうのが
問題ですが、このような方法で自動化を行っています。
balancer-manager以外でAPIなど外部からmod_proxy_balancerを操作できる方法を探していたのですが見つけることができませんでした。何かご存じの方は是非教えていただけると幸いです。
mod_proxy_balancerを利用する上での注意点
弊社で運用した経験上、注意している点があります。
1.httpd restart をすると、管理画面から動的に指定したステータスやファクターが初期化される
2.グループやワーカーの追加、削除後にgraceful restartすると動作がおかしくなる
3.1Apache上で設定できるワーカー数の合計に上限がある(?
上記には注意して運用しています。
ワーカー数の上限はメモリ管理上存在してもおかしくは無いと思いますが、正確な理由や数は調査できていません。ただ、弊社では100前後のワーカーを設定した際に、設定ファイルの下部ワーカーへリクエストがバランシングされなくなる現象を確認しました。詳細をご存じの方がいましたら、補足いただけると幸いです。
Webサーバーの再起動をしないと動的にはワーカー数を変更できない事が今後の課題です。mod_proxy_balancer以外を利用するしか無いのかもしれませんが。。
簡単なご紹介で恐縮ですが、このような方法でWebサーバー(バランサー)を利用しています。
ハードウェアにより解決するのも1つの方法かも知れませんが、ソフトウェアバランサーでも運用に対応させることは可能です。
Poundより中、大規模環境での運用は人気があると思われるmod_proxy_balancerですが
これから構築される方は、是非ご検討されるのも宜しいかと思います。
余談ですが、シャノンインフラチームでは担当エンジニアを募集中です。
プログラマからインフラエンジニアへ転向を検討されている方でもかまいませんので、
ご興味やご質問がありましたら、お気軽にご連絡ください。
https://shanon-tech-recruit.smktg.jp/public/application/add/30
3 コメント
Write コメントとても魅力的な記事でした!!
Replyまた遊びに来ます!!
ありがとうございます。。
requestcountingアルゴリズムについて教えて頂きたいと思います。
Reply振り分けで利用している各ワーカーへのリクエスト(振り分け)回数はapacheの再起動以外に手段はありますでしょうか?
また、各ワーカーのリクエスト(振り分け)回数のマックス値とその値に到達した際の振り分けの挙動はどの様になるのでしょうか?
すみません。投稿を確認せずアップして申し訳ありません。
Reply最初の質問では、apacheの再起動以外にクリアする手段となります。