天然パーマです。

「ボケて」ガンマ版リリース - 技術的新しい試みまとめ

昨日、俺が開発を務めるオモロキ発のサービス「ボケて」のガンマ版をリリースしました。 去年9月に公開したベータ版のフィードバック等を含めて、機能改善やパフォーマンス向上を行った形です。 バージョンアップに伴う詳しい変更点は、今回開設した「ボケて お知らせブログ」の以下の記事を参考にしてください。

bokete

この変更が功を奏するのか。もう既に「機能・情報過多」になって使いづらいという意見もちらほらでていたりするのですが、サイトの内容についてはもう少し様子をみてから評価するとします。 そこで、今回はガンマ版で行った多くの技術的な新しい試み、ベータ版からの変更点をまとめておこうと思います。

ボケてのシステム開発は俺一人でやっていることもあり、これまでの経験で得た知識を振り絞り、ウェブ経由を含めいろいろな方から教えてもらった情報をフル活用したつもりで、独特のものになっているかと思います。 その辺り、加味してくれて、何か参考になればうれしいです。では、ベータ版からガンマ版へ技術的にどこをどう変えたのかを紹介します。

開発体制

鎌団子と二人

人的リソースは、基本的に今までと変わらず、俺と鎌団子と二人での開発になりました。 鎌団子がデザイン及びHTMLやCSSの基本コーディング(今回は一部外注したところもあります)を担当して、 残りのシステム部分を自分が作成しました。二人で少々大変なところもある代わりに、 役割の切り分けが明確になるので、その点、すごくやりやすいですね。 サイト規模が大きくなったら考えようですが、ぶっちゃけそこまでユーザ数が多くなかったりするので、 現状はこの二人ってのが開発においては、ベストかと思います。

BTS(Bug Tracking System)の導入

バージョン管理システムには定番のsubversionを使っています。 これはベータ版の時と変わらず。 しかし、今回はTracを使ったBTS(Bug Tracking System)を導入しました。 本来の使い方と違うかもしれませんが、 以下のようにマイルストーンを切ることで目標が明確になってよかったです。
  • 01-基本機能実装
  • 02-拡張機能実装
  • 03-デザイン修正
  • 04-テスト版完成
  • 05-携帯版完成
  • 06-リリース版完成
  • 07-リリース後

あとは、 「タスク、不具合、アイデア」という具合に各チケット分類して登録するくらいで、 特別な使い方はしてないのですが、それだけでもかなり役に立ちますね。

IRCの活用

せっかく横浜にオフィスがあるので、二人が揃って開発するというのが理想ですが、 諸々の事情でなかなかそうはいかず、鎌団子@オフィス - 俺@自宅、って状況が結構あります。 そこで、オンラインでコミュニケーションをとるためにIRCを使っています。 まぁ割と一般的ですが、subversionのコミットログをPlaggerでさくっと作ったボット経由 (ってかPlagger使わなくてもできるのかな?)で流すと、 更新がすぐ確認できるのでいいですね。 以前、今やJPA(Japan Perl Association)の代表である、endewroksの牧さん達と仕事をする機会があって、 その時に同じ様な環境を用意してくれて、「これ、俺が鎌倉にいながらでも開発できるじゃん!」と発見したのが、 活かされました。うん、今更ですが、subversion + trac + IRC ってのはかなりありです。

ウェブアプリケーション

モダンPerl入門方式

さて、いよいよシステム内部の話に入ります。 開発言語は Perl、ウェブアプリケーションフレームワークには Catalyst を使っています。 これはボケてベータ版、また、いつも俺が個人で作っているアプリとも変わらずです。 ただ、今回はベータ版に比べて、「賢く」作ることを心がけました。

Catalyst は、一般的な他のフレームワークと同じく、デフォルトでは、「MVCモデル」を提供するものです。 しかし、Catalyst のそれをそのまま使おうとすると、 どうしても、Model 部分が O/R Mapper そのものになったり、Controller にロジックを書いて肥大化してしまう、 なんてことになります。すると同じことを繰り返し Controller に記述しなくてはいけなくなったり、 Web 以外のコマンドラインインターフェースから Model を扱う処理を別で書かなくてはいかなかったり、 単体でのテストが難しくなるなど、スマートと言えるものではなくなってしまいます。 そこで、MVC に加えて、実際に必要なロジックを扱う別の層を設けました。それが「API」層です。 すると、アプリケーション全体のイメージとして結果的に以下のような構造になります。

 Web
  - Model
  - View
  - Controller
API
CLI

例えば、投稿されたボケの最新20件を取得したかったら以下のように書けるわけです。

 my $api = Bokete::API::Boke->new();
my $entries = $api->get_recent( { rows => 20 } );
while( my $entry = $entries->next ){
    print $entry->title . "\n";
}

これは CLI での利用ですが、ウェブ側の Controller でももちろん似たように使えます。

と、ここまで偉そうに言ってきましたが、実はこの手法、2月に発売された牧さん執筆の「モダンPerl入門」 に書かれているものをかなり参考にしています。というか、もろそのままだったりします。 ちょうど、前述した問題も含め、「ボケてのコードもっと奇麗にしたいなー」と思っていたところに、 「モダンPerl入門」が発売されたので、実践的に本の内容を理解しつつ、 ベータ版より「賢く」作ることができたのでよかったです。

Mouseを使用

上記した API層 を作る上でかかせなかったのが、「Moose/Mouse」の存在です。 「Moose」は去年の今頃に開催された「YAPC Asia 2008」の頃に国内でものすごく話題になった、 Perl でのオブジェクト指向 (本来は Meta Object Protocol という概念なんだけど実はあんま理解してない><) を支援するためのフレームワーク/モジュールです。 オブジェクトの定義が今までと比べてかなり簡単・効率的にできるため、 API層で使うクラスを作るのに大活躍しました。 「もう Moose/Mouse がないとモジュール書けない!」とまでは言いませんが、 一度使いだすと楽ちんです。 また、Mouse という Moose 互換のモジュールを使うことにより、 体感できるほどアプリケーションの起動が速くなりました。 「Catalyst + API層 with Mouse」って手法は、個人的に今のところベストなウェブ開発法かと思いましたね。

パフォーマンスチューニング

今回の改善で実は一番気を使ったのが、バックエンドのパフォーマンスです。 自分の知識・技術不足のせいもありベータ版は全体的に、ぶっちゃけかなり遅いです。 そこで、ボトルネックはDB周りとだいたいわかっていたので、以下のような対策をしました。

  • DBのインデックスをとにかくはる
  • mysql の設定を調整、チューニング
  • テーブル定義において一部、意図的な非正規化
  • 一部、select のタイミングではなく、create/update 時にキャッシュデータを作る
  • ランキングなどの複雑なソートが必要になる部分については、定期的にキャッシュを作って、memcached に置く

これらによって、memcached によるキャッシュをしていない場所に関しても最大8倍 (後述するインフラ/サーバ周りの改善の影響も含む)の効果がありました。 まぁよっぽどベータ版が最適化されていなかったわけですが、ガンマ版では、 今のところうまくいっているようでよかったですね。

UI周り

jQuery Pluginの活用

さて、フロントエンドは「jQuery」を使用しています。これはベータ版と同じくなのですが、 「ボケを評価する」時にページをブロックさせるために BlockUI Plugin を使うなど、 なるたけ最小限になることを心がけつつ、Plugin を活用しています。 miyagawa さんが作っている Remedie ではかなり多くの jQuery Plugin を使っていて、 「おお、こんな Plugin あるんだ」と参考にさせていただきました。

jQuery UI ベース

また、今回の UI は実験的に「jQuery UI」をベースとしました。 この jQuery UI は名前の通り jQuery を使ったユーザインターフェースのフレームワークなのですが、 CSS セットが用意されているのが今回導入したきっかけです。 これを使えば、角丸のアイコン付きボタンなんてものが、比較的簡単に作れてかつ、 HTML・CSS はそのままでテーマを切り替えることが可能です。 ただ、その反面、ユーザサイドのブラウザによるレンダリングに負荷がかかってしまったり、 IE では角丸が効かなかったりと弊害もあるので、その辺りは今後評価していきたいです。

インフラ・サーバ

Amazon ec2 から自宅サーバへ移行

これまでサーバは Amazon ec2 上で動かしていたのですが、今回ガンマ版公開にあわせて、 自宅サーバに全て移行させました。その一番の理由がコストです。 ベータ版では、ec2 のインスタンスを3つ立ち上げ、 「フロント - アプリ - DB」という割と mod_perl を使う上で一般的な構成にしていました。 ec2 のインスタンスは一番安いものを24時間常時起動させておくと一つ当たり最低でも「約7,200円」月額でかかります。 それが3つとなると、「21,600円」。ベータ版では一部、CPUが2コアのものを使っていたので、 回線使用料金なども含めてそれよりももっと高額になります。 これが他のメリットとあわせて安いとみるか高いとみるかは状況によりけりですが、 自分は「高い」との判断をしました。その代わりとして、 一番の選択肢にあたったのが自宅サーバ環境での運用です。 そもそも、個人的な他のサービスを自宅サーバで動かしていることもあり、 回線、ルータ、UPS等のインフラはそこそこのものが揃っているので、 追加でかかる費用が、サーバ用マシン本体の値段及び電気代くらいになります。 その辺りを加味すると自宅サーバでも以前と同じもしくはそれ以上のスペックで、 さらに「安く」運営できるのです。 ちなみに、ボケてで投稿されたお題の写真は Amazon S3 に置いて配信していたのですが、 こちら S3 は、もろもろ計算すると ec2 とは違い「安い」ので、 ガンマ版でも継続して使っています。

充実してきた自宅サーバルーム(納戸)の様子
server

仮想化 + USBメモリブート + iSCSI

さて、ec2 では3つインスタンスを立ち上げていたわけですが、 かといって自宅環境に3つのマシンを置くようなことはせずに、 OSを仮想化させてなるべく少ないマシン、そして省電力でまかなえるようにしました。 いろいろと調査及び検証を行った結果できたこのサーバ周りの仕掛け。結構面白いことになっています。 最初に、簡単に構成をまとめると以下の通りです。

  • iSCSI ターゲットサーバ用マシン
    • RAIDで組んだ1TBのディスク
  • VMware ESXi 用マシン
    • USBメモリで VMware ESXi を起動、ディスクレス
    • WebとDB用の2つの VM をiSCSI上に構築

今回追加したマシンはこの2つで、iSCSI ターゲット用マシンは「ボケて」以外でも使えるので、 実質的に「ボケて」用というのは「1.x」台のマシンと言えます。

では、簡単にひとつずつ解説してみます。

まず、仮想化についてですが、CPU の高速化・マルチコア化、大容量メモリの値下がりによって、 1台のマシンに複数の VM を起動させてパフォーマンスを発揮させることが可能になったことで、 特に自宅サーバで運用する場合においてかなり有効だと思います。 その仮想化環境として今回、使用したのが、「VMware ESXi 3.5」です。 ちょうどいいタイミングで citrix 社の「XenServer」が3月末に無償化したので、 興味を持ってそれを使おうと思ったのですが、 どうも調べていくうちに「VMware ESXi」も無償であり、かつ情報も豊富ということがわかったので、 結果的に VMware を使うことにしました。 XenServer の方が機能が多くて管理用のソフトウェアも使いやすいのですが、 反面、複雑でわかりにくいというのも XenServer を却下した大きな理由です。

で、「VMware ESXi」を使って1つのマシンに2つの OS を立ち上げているわけですが、 このマシン自体は USBメモリ で起動しています。 どういうことかと言うと、 VMware 自体をブート可能な状態で普通の USBメモリ にインストールして、 ハードディスクなどその他記憶領域を持たないボケて用のマシンにぶっさしているのです。

安売りしていたdellのサーバにUSBメモリをさしている
server

「それじゃあ、VMの記憶領域はどうなるの?」ということになりますが、そこで iSCSI が登場します。 iSCSI は ネットワーク経由で iSCSIターゲット上の 記憶領域を他のマシンからマウントすることができる 技術で、NFS 等と比べてリード/ライトの速度が速いことが特徴です。 「VMware ESXi」では iSCSI をサポートしているので、別に立てた iSCSI ターゲットマシンの、 一部ハードディスクを利用してその上に OS のデータを置くことができるのです。

こうすると何が嬉しいかと言うと、 1台の iSCSIターゲットの記憶領域を複数台のディスクレスのPCから利用することで、 省電力化が図れるのではないかと思っています。 パフォーマンスも今のところ問題なく、I/O のスペックが影響する DB も機能しています。 今のところボケて用マシン1台が iSCSI を利用しているだけですが、 今後サーバを立てたいという時には、最低限、マザーボード・CPU・メモリ・電源があればいいので、 安上がりかつ電力消費も少なくなるというのが嬉しいところです。

apache から lighttpd へ

最後に、ベータ版からガンマ版で大きく変わった点として、 ウェブサーバを apache から lighttpd にしたことが挙げられます。 今まで「apache 使っとけばいいだろ」と思って lighttpd に全く触れてなかったのですが、 すすめられて使ってみたらすごいいい感じです。 lighttpd + fastcgi の何がいいって、パフォーマンスのこともさることながら、 アプリケーションの切り分けが可能なことです。 もしかしてできるかもしれませんが、apache + mod_perl で運営していた時には、 複数のアプリケーションを1つの apache で動かす場合に、同じメモリ上にモジュールを読み込むために、 メモリ効率が悪かったり、複数アプリ間でモジュールの衝突が起こる可能性があったりしました。 lighttpd + fastcgi の場合はアプリごとに起動なので、上記の問題も解決して、 プロセス数の調整なども個別にでき、さらに静的コンテンツのサーブも面倒をみてくれます。 これも少ないマシンで複数のアプリケーションを立ち上げたいという自宅サーバ環境にとっては、 嬉しい点です。

まとめ

エントリーとしてずいぶんと長くなってしまいましたが、 その分いろいろと技術的な試みをしてみて、その点今回は非常に楽しい開発・環境構築になりました。 しかし、こうした技術はいいコンセプト・機能があってこそのもの。 ガンマ版になった「ボケて」。次のバージョンアップも含めてこれからよりいいものにしていきたいです。

モダンPerl入門 (CodeZine BOOKS)
posted with yusukebe.com::AmazonSearch on 2009.5.2
  • 牧 大輔
  • 大型本 / 翔泳社
  • Amazon 売り上げランキング: 11574
  • Amazon おすすめ度の平均: 5.0
    • 5 perl経験者は読んで損はしない
    • 5 Perl中級者におすすめしたい
Amazon.co.jpで詳細を見る

写真で大喜利ボケて (コアムックシリーズ (NO.396))
posted with yusukebe.com::AmazonSearch on 2009.5.2
  • ムック / コアマガジン
  • Amazon 売り上げランキング: 17262
  • Amazon おすすめ度の平均: 4.5
    • 3 恐らく最初で最後の書籍化記念として
    • 5 写真で一言を自分でやってみる
    • 5 PCに埋もれた秀逸ネタをチェック!!
Amazon.co.jpで詳細を見る