Webサーバーをスケーリングと冗長化のためにロードバランサ (LB) を
使用するシステムは珍しくないと思う。
ただ、手元の有り合わせの環境で簡単な性能検証をする際には
ネットワーク機材をそろえる事が難しい事も多い。

そんな時、私はpoundを使用していた。
pound は 適当な Linux サーバーにインストールすればすぐに使用できる。

でも、最近 pound では性能が不足する事が出てきた。

LB は、HTTP の通信を右から左に流すだけの物。
正直、そんなにリソースを使用するとも思えないのだが、
性能を測定したいサーバーよりも先に LB にボトルネックが来てしまう事は困る。

mpstat を見てみると、マルチコアのサーバーにインストールしているにも関わらず、
1個しかコアを使用していない模様。

これでは、サーバーを増強しても簡単には LB がスケーリングするとは思えない。
というわけで、Linux のプログラムとして動作する他の LB を探してみた。

十分な性能がでそうな候補として上がったのが、以下の 3個。
Apache のモジュール、mod_proxy_balancer
勉強会で聞いたところによると、gumiさんはAmazon Web Service のサーバー 1~2 台に mod_proxy_balancer をインストールし、最大3000万PV / 日 をさばいているとのこと

nginex (低機能、高速が売りの Web サーバー、リバースプロキシ)
勉強会の後で講師のgumiの堀内さんに伺ったのだが、mod_proxy_balancer より nginex の方が速いらしい。
(でも、Apache のノウハウが使えるから mod_proxy_balancer を使用中との事)

HAProxy
公式サイトに性能検証の結果が出ていた。
PenM 1.7GHz で 19000リクエスト/秒をさばいている。


上記 3個の LB は、その通りの性能が出れば私の性能検証には十分すぎる。
せっかくなので、振り分け方法も調べてみた。

1. ラウンドロビン以外の振り分け方法
ラウンドロビンだと、どうしても特定の Web サーバーに負荷が集中する。
実際の運用では気にならないかもしれないが、性能検証の際にはありがたくない。
できれば、Least Connections とかで振り分けられるとうれしい。

調べたところ、mod_proxy_balancer はラウンドロビン、又はトラフィック量のみ
nginexとHAProxyは Least Connections で振り分け可能な模様。

2. L7 の機能
同一セッションのリクエストに対し、同じWebサーバーに割り振る事ができるか。
例えば、初回ログイン時に、user1 はたまたま web1 に振り分けられたとする。
すると、ログアウトまで user1 は web1 に振り分ける事ができるか。
もしこれが出来れば、セッション情報を各 web サーバーで勝手に保存できる。
セッションの閲覧、更新の際のデータベースへのアクセスが無くなるのだ。

調べたところ、mod_proxy_balancer はリクエストの URL や Cookie を解析して、特定の web サーバーに振り分ける事が可能。
例えば、webサーバーごとに異なる Cookie を発行すれば、L7 で振り分ける事が可能だ。
対して nginex は、現在の所 L7 の振り分けが全く出来ないように思われる。
最後に、HAProxy は、mod_proxy_balancer のように L7 で振り分けが可能。
さらに言うと、HAProxy 自体が振り分けのための Cookie を発行してくれるので、Web サーバーに手を入れる必要が無い


実際にインストールして色々と試したが、次回の性能検証では HAProxy を
使用する事に決めた。

っていうか、最近のアプリケーションタイプ LB って、ずいぶん性能が良いようだ。
これじゃ、LB 売ってる会社は大変だろうな。
Webのソーシャル時代を担う「Python & Ruby」に行ってきた。
講師は「株式会社 ゼロスタートコミュニケーションズ」という会社の
山崎さん。(社長さんらしい)
「Python & Ruby」という表題だが、実質的には Python の勉強会だった。

講演中に山崎さんもおっしゃっていたが、Python は中級者向けの
勉強資料(日本語)が少ない。

別に言語の構文とかコードリーディングについては、英語のドキュメントがいくらでもある。
でも、現在の流行とか、現場の声を気軽に聞くことができる環境が無いと、
"Hallo World" の次に何を学べば良いのか分からない。
そういった意味で、今回の勉強会は大変参考になった。

講演内容は、前半が WAF (Web Application Framework) を中心とした
Python の紹介で、後半が実演(その場でウェブアプリを作成)。

Python の紹介内容は、だいたいこんな感じだった。
(私の解釈も含まれているので、山崎さんの意図と若干異なるかもしれないが、
  そこはご容赦をしてください。)
・Perl に比較して WAF が速い
  (Perl の場合、それぞれ異なる Author が作成した多くのモジュールを使用する。
    そして、モジュール単位で抽象化やサニタイズを行うので遅くなるというご意見)
・言語自体が、オブジェクト指向で設計されている
・インデントが構文に含まれているので、読みやすい
・GAE (Google Apps Engine) などでも使用可能。
  おそらく、Google は利用ユーザーは Python を使用する事を
  想定している模様。
・現在、バージョン2から3への移行中
  今から始めるのであれば、2系の方が良いと思う。
・日本では Ruby の方が有名だが、世界では Python の方が有名
  今後は、日本でも Python が主流になるのではないか


また、Python で有名な WAF として、Django, Turbogears, Tornade の
簡単な紹介もしてくださった。
Django
・MVC ではなく、MVT
  Cは無い。(URLと関数のマッピングのみ)
・テンプレート機能は弱い
  最近、if などをテンプレート中に書く事ができるようになった。
  テンプレート中の足し算などはまだできない。
・現在、山崎さんがメインで使用している

Turbogears
・今はあまり使用されていない。
・SQLObject, Kid など、一部の機能を切り離して使う事が可能
  (山崎さんも時々使用するとの事)

Tornade
・Facebook の使用しているフレームワーク
・まだ機能が充実していないが、超高速
・ノンブロッキング
・nginx と併用する事が多い



講演を聞いて思ったのが、今後は Python の方が主流になるだろうと言う事。
Ruby 大好き人間としては悔しいが。

Python には、実装方法が 1種類であるべきという思想がある。
(There should be one―and preferably only one―obvious way to do it)

例えば、ループを回す際に、それぞれ
・Python では for 文を
・Ruby では each メソッドを
良く使用する。

そして、Python も Ruby も共に、これらのループに関連した
便利な機能を、デフォルトで多く持っている。
(両者で似た機能も多い。)

しかし、Ruby の each はメソッドなので、上書きが可能だ。
そして、each を上書きすると、内部的に each を使用する
他のメソッド(例えば map)も上書きされる。

でも、Python ではそれが出来ない。


いわゆる「中2病」をこじらせたような人には
このような Ruby の特性は面白いだろうし、
世間で天才と呼ばれている人には、これが Python の機能不足と
思えるかもしれない。

Railes が Ruby で作成されたのは、このような言語の特性が
大きく影響しているのでは無いか。

でも、これらの特性は逆に Python の保守の良さと
解釈する事もできる。

グローバル変数を多用がバグの温床となるように、
必要以上の自由度は無い方が良い事も多い。

また、実演を見て思ったのが、他人のコードを本当に読みやすい。
今まで他人が書いた Python のコードはあまり読んだ事が無く、
今回初めて実感した。

Ruby は実験的な新しいアイディアのが湧きだす
魔法の言語かもしれない。
でも、私のような人間がつくる平凡なアプリは、
これから Python の実装が増えていくような気がした。
なんか、Ruby 1.9.2 のベータ版がダウンロード出来るらしいので、やってみた。

東京と仙台の Ruby 会議で色々な人から伺った事をまとめると、以下のような感じ
1. Ruby 1.9.2 のソースは subverison のトランクからダウンロード可能
2. Ruby 1.9.2 は Linux では Rspec も全て通った。
   ただ、Windows ではうまくいかない所がある
3. 今まで Ruby 2.0 でやる予定だった事は、だいたい Ruby 1.9.2 で実装してしまった
   Ruby 1.9.2 は長期安定版のリリースになるかもしれない

(私もアルコール入っており、メモはとっていない。
記憶ベースだし、賞味期限の短い話題なのであまり参考にしないでほしい。)

まあ、何はともあれ Linux で 1.9.2 が動くとの事なので、手元の環境でビルドしてみた。
ちなみに、環境は Ubuntu 9.1.0

1. 必要なツールのインストール
   $ sudo apt-get install autoconf
   $ sudo apt-get install bison

他にも、make と svn も必要なので、入っていない人は入れてください。
(私の環境には、既に入っていた。
でも、Ubuntu に元々有るものか自分で入れたのか忘れた。)

2. ソースのダウンロード
   $ mkdir tmp && cd tmp
   $ svn co http://svn.ruby-lang.org/repos/ruby/trunk ruby192
   $ svn info ruby192

このようにすれば、subversion から最新版のソースをダウンロードしてくれる。
ただし、trunk の中の最新版なので、バグも多いから注意。

3. ビルド、インストール
   $ cd ruby192
   $ autoconf && ./configure --prefix=/opt/ruby192/27219 && make
   $ make install

configure の prefix オプションは、インストールディレクトリを指す。
私がビルドした際のソースはバージョン27219だったので、
27219というディレクトリを作成した。

4. パスを通す
   $ cd /opt/ruby192/27219/bin
   $ for f in `ls`; do
   > sudo ln -s /opt/ruby192/27219/bin/$f /usr/local/bin/$f
   > done

普通の人は、$PATH を追加すると思うが、
私は /usr/local/bin 以下にリンクを作る方法が好き。
(普通の環境では、/usr/local/bin には初めからパスが通っていると思う)

5. 確認
   $ ruby -v
  => ruby 1.9.2dev (2010-04-05 trunk 27218) [i686-linux]

確かに、ruby 1.9.2 がインストールされている。

以上、ビルド終了。
1.9.2 の主な変更点は成瀬さんが記載してくださっている
るびま29号

とりあえず触ってみる程度の範囲では、以下の影響範囲が大きそう。
$LOAD_PATH からカレントディレクトリの削除

セキュリティ上の懸念から $LOAD_PATH ($:) からカレントディレクトリ (.) が削除されました。これに依存していたスクリプトは require_relative を用いるように書き換えることが推奨されます。


あと、さらっと書いてあるけれども、場合によっては既存のコードに
致命的な影響を与えそうなのが以下
(ただし、1.9.1 でも変更されるみたい。)
正規表現における \d、\w、\s の ASCII 化

以前の Ruby 1.9.1 では \d、\w、\s は Unicode を意識した定義になっていました。具体的には /\w/ =~ "あ" がマッチしたりしていました。この挙動は当初の想定以上に実世界で問題を起こすことが判明したため、バグとみなされ、Ruby 1.8 同様 ASCII のみにマッチするように変更されました。なお、この変更はバグ扱いであるため、Ruby 1.9.1-p376 にも取り込まれています。

以前のように Unicode を意識して欲しい場合は、\p{Number}、\p{Word}、\p{Space} 等を用いてください。


まあ、1.8.6 -> 1.9.1 の時よりも、1.9.1 -> 1.9.2 の方が
仕様変更は少なそう。
(当り前か。)

皆さん、良い Ruby Life を。