2010年1月29日金曜日

オープンソースで構築する非同期分散処理のプラットフォーム

先日のエントリでお伝えした通り、現在新しいビジネスの立ち上げに奮闘してます。

その中で、最近流行(?)の非同期に分散処理するようなプログラムを書きましたのでそれについてエントリを書きたいと思います。

今回作っているビジネスモデルは基本的にサーバーサイドのアプリケーションのリソースを切り売りしていくモデルで考えているのですが、その中で非常に重たい(時間のかかる)処理が存在します。

これを非同期分散処理を行う事で、待ち時間を感じさせないよう工夫しました。Movable Typeを使った事がある方は理解出来ると思うのですが、やっている事は本質的に静的構築とあまり変わりません。あらかじめキャッシュを生成するようなイメージです。

実際の処理の流れを、福岡ITベンチャーヌーラボさんのCacooを使って簡単に図にしました。



図のブルーの図形で囲まれたところが今回開発した処理の部分です。この部分をGearmanというフレームワークを使用して実際の処理を実装しました。本家の図が非常にわかりやすいので、これを用いて簡単にGearmanの説明を。



見ての通りGearmanを使うだけで、Client Application Code(呼び出すときのプログラム)と、Worker Application Code(呼び出されるときのプログラム)の二つを書くだけで非同期処理に必要なAPIやJobQueueの仕組みはすべてGearmanが面倒みてくれます。とても便利!

しかもClient Application CodeとWorker Application Codeは同一の言語で記述する必要がありません。現に今回はClient Application CodeはPHPで、Worker Application CodeはPerlで記述しています。

ではCacooの図に戻って、ブルーの図形の部分は順番に、

  1. APIサーバ: CakePHP, Gearman Client(Gearman PHP Extension)

  2. ジョブサーバ: Gearmand(C実装版)

  3. 変換サーバ: Gearman Worker(Perlで実装)

  4. ストレージサーバ: Apacheが稼働している

となっていて、今回書いた実際のコードはAPIサーバのコードと変換サーバ部分のコードだけです。

ジョブサーバのコードは一切書いていません。これはすごい便利ですよ!

といいつつ、これだけでは何故非同期処理や分散というキーワードが出てくるかわかりにくいのでもう少し突っ込んで解説します。

今回の処理で一番メインの処理は変換サーバの処理です。変換サーバは大きなあるデータを別のデータに変換する事をやってくれるのですが、これが非常に重たい。

そこでAPIサーバからジョブサーバに処理を委託した後、APIサーバはサービスサーバに受付が完了した情報を発行します。ジョブサーバには処理がたまっているので、変換サーバがひとつずつ処理し、結果をまたAPIサーバに返し、APIサーバがそれをサービスサーバに通知して一連の処理が完了します。これを繰り返しているのです。この時変換サーバの処理が重たくても、一時的にAPIサーバが受付完了をサービスサーバに発行するところがキモであり、レスポンス待ちを出来る限り発生させないところが一番オイシイところです。

まだわかりにくい?わかりにくいですよね(笑)

現実のものに例えば方がわかりやすいので、この仕組みを銀行を使って説明します。

銀行へ言って、窓口で口座を開設する時の事を思い浮かべて下さい。まずいきなり窓口へ行く事はなく、最初に整理券を取るでしょう。このときに既にお客さん10人待っていれば11人目になりますね。しばらく待って、整理券に記載された番号を呼ばれれば窓口へ出向き、口座開設の手続きをする。

まさにこの仕組みとそっくりなんです。

  1. 整理券を取る: APIサーバジョブサーバへ作業依頼

  2. しばらくまつ: ジョブサーバで順番待ち

  3. 番号が呼ばれ窓口で口座開設の手続きをする: 変換サーバが実際の処理をする

この通り、似てると思いませんか?

そしてここからが面白いところ。
実際に銀行の窓口は一つだけという事はなく、複数の窓口が設置されていたり、依頼内容によって窓口が異なっている場合が多々あります。
例えば預金口座の開設と借入の為の窓口は別だったりします。また、借入を希望する人が多いと予想される場合はローン申込の窓口を増やしたり、ニッチな要求かつクリティカルな要求(盗難や紛失など)は単独で窓口を設けていたりますよね。

変換サーバ(というかWorker Application Code)はまさにこれと同じであり、窓口を増やしたり減らしたりする事が出来ます。
例えばよくある最初に発生する膨大なスイッチングコストの発生時期だけ大量にWorker Applicationを起動させ処理し、落ち着いたら減らしてマシンリソースを節約。なんて事が可能です!

新機能を取り入れた一部の人にベータ公開したい時や、特急料金を払ってでも速く要求に答えて欲しいときなど、実際のビジネスシーンにおける様々な個別要件を実際にWorker Application Codeとしてあらかじめシステムとして組み込める事がとてもやりやすい。また、突発的に発生した特殊要件についても既存のClient, Worker処理を止めたりする事なく追加したり取り出したり出来るところも簡単に出来るようになっています。

このようにGearmanは大変手軽に組み込めて、各処理は自分の好きなプログラミング言語でかけるというとても素敵なプラットフォームというわけです。非同期に大量のデータを分散処理したいなら、まず検討してよいプラットフォームといってよいと思います。

参考までに現在の構成は、

ジョブサーバ: 1CPU
Client Application: 1CPU
Worker Applications: 6CPU

ですが、大変安定しています。既にジョブサーバはリブート無しで10万件近いジョブを処理しましたが至って安定しています。
非同期処理や分散処理に興味ある方、Gearmanは手軽でオススメですよ!

0 件のコメント:

久しぶりにブログを書く

最初ログインできなくて焦った。 いや、ログインはできたのだが、ログイン後に自分のブログの管理画面に遷移できず、新しいブログを作成する画面になってしまったからビビッてしまった。 どうやら、Google+(現在はサービス終了)に紐づいたプロフィールを設定しているとこのような状況に陥る...