もう朝が近いな・・・。

Kodougumod_proxy_balancer でロードバランスしたのですが、Ajax のレスポンスが 10 秒以上待たないと返ってこないという問題に遭遇してしまいました。具体的には、ブラウザ(FireFox)上でモデル要素を動かすと、Ajax リクエストを送信するのですが、これのレスポンスが 10 秒以上たたないと返ってこないという現象です。Apache の httpd.conf をいじって KeepAlive を外したら速くなったのですが、どうも腑に落ちません。

昔、IE では KeepAlive 関係でバグがあってレスポンスが返ってこないというのはあったようですが、今回は FireFox なのでちょっとそれはなさそうな予感がしています。

以下のバグが少し関係ありそうなのですが、効果がないと書いている対処法が、私のケースでは効果があったので別問題でしょうか。時間のあるときに Apache の bugzilla をあさってみますかね。やれやれ・・・。

Bug 37770 - proxy: error reading status line from remote server (null) | Apache | Bugs
http://www.gossamer-threads.com/lists/apache/bugs/314332

■ 追記(2007/3/4 13:24)
上記の Bug 37770 に関係があるかと思い、以下の記述にしたがって httpd.conf を修正してみました(つまり、KeepAlive を On にして、以下の記述を追加した)が、効果はありませんでした。うーん・・・。

mod_proxy - Apache HTTP サーバより:
[code:

SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1]

当面は KeepAlive Off でいくことにします。しばらくはこういった問題がシビアになるほどアクセスが集中するとも思えないので。

○ 問題の整理
Apache(mod_proxy, mod_proxy_balancer)をフロント、Mongrel(Rails)をクラスタリングしてバックエンドに配置した状態で、ブラウザ(FireFox)上でページ遷移のない Ajax を多用した操作を行うと、Ajax レスポンスが返ってくるまで KeepAliveTimeout + サーバの処理時間程度の時間がかかってしまう。(私の環境では、KeepAliveTimeout は 15 に設定しているので、15 秒以上待たされる。)
しかし、ページ遷移のある操作は問題なく動作します。

Posted by あかさた
今日は、Kodougu 公開に向けて、Apache2.2 で mod_proxy_balancer を使ってロードバランスを実現させるということをしていました。つまり、フロントエンドを Apache(mod_proxy, mod_proxy_balancer)、バックエンドは Mongrel という Rails の世界では割と一般的な構成にしました。役割としては、Apache がロードバランスして、Mongrel がリクエストを処理します。Mongrel とは Ruby で書かれた Web サーバで、Rails アプリを動作させることに適しています。

なぜこのようなことをしているのかというと、理由は二つあります。ひとつはパフォーマンスとスケーラビリティに関係するものです。Mongrel は Rails アプリを動作させるには非常によい Web サーバ(Rails と相性がよくて高パフォーマンス)です。しかし、Apache と同じく 1 プロセス 1 コネクションであるため、クライアント(ブラウザ)に直接接続させてしまうと、大量のリクエストが発生したときに(Kodougu では大量のリクエストが発生する)、Web サーバがビジーになって、リクエストを受け付けるまでラグが発生する可能性があります。そこで、複数の Mongrel プロセスを起動して負荷を分散します。Mongrel はロードバランスはしてくれないので、Apache にロードバランスさせているというわけです。
もうひとつの理由は、Mongrel は Rails に特化した Web サーバなので、フロントには別のサーバをおいておきたいという思いがあります。そこで、普段使い慣れている(+ロードバランス機能を持った)Apache をフロントに置き、Mongrel をバックに配置しました。

さて、設定は楽勝なのですが、mod_proxy_balancer で一点はまりました。mod_proxy_balancer を使うために httpd.conf には以下のような記述を追加します。(実際にはもっとたくさんのバランサメンバがいます。)

ProxyPass / balancer://mycluster/
ProxyPassReverse / balancer://mycluster/
<Proxy balancer://mycluster/>
  BalancerMember http://127.0.0.1:3000 loadfactor=20
  BalancerMember http://127.0.0.1:3001 loadfactor=20
</Proxy>


balancer://mycluster/ の最後のスラッシュ(/)を書かなかったがために、ルート以外の URL にアクセスしたときにパーミッションエラーになってしまいました。
# これで何時間もはまってました。。。

気をつけませう。。。orz

Posted by あかさた
Kodougu の運用環境に Apache2.2(mod_proxy, mod_proxy_balancer)+mongrel を使用しようと考えています。そこで、gem を使ってサーバ(Fedora6)に mongrel をインストールしようとしたところ、以下のようなエラーが出て失敗しまいました。

Building native extensions.  This could take a while...

ERROR: While executing gem ... (Gem::Installer::ExtensionBuildError)
ERROR: Failed to build gem native extension.

ruby extconf.rb install mongrel
can't find header files for ruby.

これは、ruby-devel をインストールし忘れていたからで、ruby-devel をインストールしたところ、無事 mongrel のインストールに成功しました。

yum install ruby-devel


Posted by あかさた
ものすごい亀反応ですが、Rails Engines が Rails 1.2 でも使えるようになりました。一つ前のニュースを読むとおり、Rails のバージョンが 1.2 にあがったときに、互換性の問題で Engines は使えなくなっていました(Engines are dead...)。しかし、2/4 のリリース(Engines 1.2)ではこの問題が解決されているようです。

ってことは、Kodougu でも Login Engine は使えるな~。

Posted by あかさた
そろそろ Ruby の勉強を本格的にしたいと感じたので、まずは動的にクラスを定義する方法を調べてみました。以下のコードでは、動的にクラスを定義して、アクセッサ(my_name)を追加しています。

# Class の定義
my_new_class = Class.new
my_new_class.class_eval("attr_accessor :my_name")

# Instance の生成
my_new_object = my_new_class.allocate

# 生成した Instance を使用する
my_new_object.my_name = "akasata"
printf "My name is %s!\n", my_new_object.my_name

ここまでは楽勝です。さすがは Ruby。(LL では大抵楽勝だと思いますが。)

Posted by あかさた
Delphi for PHP が出るそうです。Delphi の名を冠していながら、Delphi 言語では開発できないなかなかナイスなシロモノのようです。RAD だから、IDE だから、というか、ツールが Delphi っぽいから Delphi の名前がついたみたいですね。
# だったら Delphi 言語なんて名前にしないで Object Pascal で良かったじゃん!
## と、随分昔の話題を蒸し返してみる。

もう少し Delphi にはがんばってほしいのですが、Kylix や Delphi for Java といっていたときのような気概を感じられないのがなんとも残念です。これじゃお布施は集められないな~。


Posted by あかさた
Rails勉強会@東京第15回に参加して、Rails 1.2 に関する情報を収集できたので、Kodougu を 1.2(これまでは 1.1.6)に上げてみました。

後悔した。orz

やってみたところ、DEPRECATION WARNING が大量に出てしまいました。@header(推奨は @ を外す)とか start_form_tag(推奨は form_tag)とか修正箇所は 100 箇所近くに及びました。(コード総数は 1500 行程度だったと思います。)
# 1.2 以前に既に Deprecated になっていたものも混ざっているようでしたが・・・。

まあ、修正の絶対量はたいしたことがないのですが、困ったのは、Ajax を使った機能でレスポンスが 30 秒位たたないと返ってこないという現象が発生したことです。最初は、私のコードに根本的な問題があって、Rails 1.2 ではこのパフォーマンスしか出ないのかと勘違いして、冷や汗・・・というか恐怖すら覚えました。(^^;
結局、@header を修正したら収まって、従来どおり 0.2 秒位でレスポンスがくるようになりました。DEPRECATION WARNING が大量に出ると、処理が重くということでしょうか。

まあ、結果的にはどうということもなかったのですが、あまり心構えをしないではじめたせいで心臓に悪い作業になってしまいました。(^^;

Posted by あかさた
2/16 にポジションペーパーを作りましたが、昨日(2/18)はRails勉強会@東京第15回に参加してきました。参加したセッションは以下のとおり。
・ Rails v1.2 の変更点と REST との関係
・ Agile Model Driven Development with Rails

以下に簡単な感想を記述しておきます。

■ 勉強会の形式
オープンスペース形式で全後半のセッションがありました。自己紹介はポジションペーパーを使いましたが、ネタでアイスブレーク(かなりイタイです^^;)をしたりとか、柔軟に運用していました。

■ 参加者
この勉強会には SIer、Web 系、研究系など意外と幅広い方が参加されていました。やはり、この手の勉強会は刺激になります。こういう勉強会がないと、高いスキルを持った人と出会う機会がないですからね。
# いや、別に前の会社でそういう出会いがなかったと言うわけじゃないのですが。

■ 雰囲気
ライトニングトークスとかではないので、若干まったりした雰囲気も漂いつつ、そこそこ濃い話をし合う勉強会だったと思います。「こう書くと気持ちが良い」という議論が多いのはこの手の勉強会ならでは。Rails の勉強会は、Java をやる人が多いせいか、若干 Java 世界の香りもしました。

■ 内容
Rails のようなフレームワークを使っていると、悪い意味でのアジャイル(安い、早い、マズイ)と誤解を受けることがあります。この勉強会では Rails はどちらかというと対象としている領域に対しては、しっかりとした理論的な下地を持った「良い意味で堅いフレームワーク」ということが実感できました。
# scaffold があるからって Rails 風を名乗るなよ!
# それは単なる宣伝文句なんだ。鵜呑みにしちゃだめだ!

モデリングにもそれなりの関心が払われていることは興味深い現象でした。もちろん、UML 限定とか狭義のモデリングではなく、開発に必要な情報を集めて整理してから開発を進める必要性をちゃんと認識しているということです。

あと、勉強会で人の話を聴いていくうちに、Rails はもっとうまく使ってやらないとかわいそうだと実感しました。使い方によっては、もっともっと高い生産性を発揮できるフレームワークなんですね。
# やはり scaffold だけじゃない。

■ お礼
最後に、勉強会を運営してくださった皆様(特にドリコムの方々)は、お疲れさま&ありがとうございました。

Posted by あかさた
すでに気づいている人も居るかもしれませんが、記事の右下にいくつか記事と関連のありそうな単語が並んでいると思います。タグです。このブログにタグを実装してみました。そこの単語をクリックすると、タグと関係のある記事が表示されます。

記事とタグの間の関係を表すクラス図は以下のとおりです。

1171499624_20070215_01.png

上の図は Kodougu で書きました。(これがやりたかった。^^)何をやっているのかというと、クラス図のメタモデル(ストラクチャとノーテーション)を設計して、設計したモデリング言語(クラス図)を使ってモデリングして上図を作成したということです。上図の場合、モデリング言語設計は 10 分くらいでできました。

もっとも、Kodougu のモデリング言語設計機能では、多重度が多の関連(属性)を要素に追加することが出来ないので、クラス図に属性をつけることはできません。
# 今がんばっています。

余談ですが、上図のような多対多の関連を実現するために、Rails ではテーブルを一つ作って、habtm という関連を作っています。(articles, tags, articles_tags という三つのテーブルが存在して、多対多関連の実現には articles_tags を使っています。habtm は has_and_belongs_to_many の略で、これを ActiveRecord で指定すると、多対多のテーブルの情報を使って自動的に関連を再現してくれます。)タグ実現の具体的な作業としては、ソースコードを自動生成したらドメインオブジェクトに habtm を一行追加して、ビューとコントローラを整えるだけです。なんというか、便利な世の中ですねぇ・・・。

Posted by あかさた
Kodougu では、SQL の Select における N+1 問題を回避することが重要になってきます。

N+1 問題とは、Tree 状の情報を DB から読み出す際、全レコードの取得に一つ+各レコード分だけ SQL を発行してしまう問題です。出来の良い O/R マッパーを使っているとよく引っかかります。

Kodougu のようなモデリングツールだと、この問題には非常によく出くわします。例えば、図上の要素を全て取得してから、要素に関係する関連の一覧を取得するなどを行うような場合です。Rails の ActiveRecord は気軽に DB にアクセスできてしまいますから。以下のコードでは、要素から出て行く関係線の一覧を取得しています。以下のようなコードを書いてしまうと、図を一枚描くたびに要素数分の SQL が発行されてしまいます。
[code: @elements = Element.find(:all) # DB アクセス発生

for element in @elements
@outputs = element.outputs # DB アクセス発生
end]

この問題が深刻な理由は、「DB サーバはアプリケーションサーバと比較するとスケールさせにくい」からです。昨今の流行りでは、アプリケーションサーバはステートレスですから、ロードバランサーを入れるだけで簡単にクラスタリング可能です。しかし、DB サーバはレプリケーションに対応していたとしても、同期の問題などがあり単純にスケールさせることは非常に難しいのです。そこで、アプリサーバで CPU パワーを多少使ってもかまわないから、DB への負担を減らしておいた方が、スケールするアプリが書けるというわけです。

今のところ、Kodougu では個別ケースの対処ではありますが、DB にアクセスするときに、必要な情報を DB から全て取得してから、アプリケーションサーバ(Rails)やクライアント(JavaScript)でオブジェクトグラフを再構築してアプリで利用するということをやっています。

この問題をある程度自動的に回避するライブラリを作らないと身が持たないかも・・・。
# 実現方法についてはまだノーアイディアですが・・・。

Posted by あかさた