脱OpenPNE。 - Lang-8でRuby on Railsを採用

Rails導入の背景

永らくOpenPNEベースで開発を続けていたLang-8ですが、以下のような課題を抱え続けていました。

もうそろそろ、何かフレームワークを導入するべきだろうと。

スケールするの?

フレームワークを選定する上では、DB周りがスケールするかどうかを最重要視しました。
たとえばRailsのO/RマッパであるActiveRecordは単一DBを前提にしており、スケールさせることが難しいらしい、なんて話を聞きます。メインのDBをActiveRecordで構築しなおすのはいやだなー、と。データ移行の手間もあるし。。。SNSにとってボトルネックは常にDBなので、サイトのコア情報を引っ張ってくるSQLは、やっぱり直に書けるほうがパフォーマンス面で安心感があります。

またLang-8ではDB負荷を軽減するため、OpenPNEのDB周りに大幅に手を入れて、Memcachedを多用した設計に作り直していました。このあたりのコードは新体制でも引き続き使いまわしたいところです。

Ruby未経験

Rubyは自分にとってはじめての言語。フレームワークであるRailsの習得にも時間を要することを考えると、一挙にサイト全体を全面移行させるのはかなりつらい。。

結論:内部WebAPIによりフロントエンド/バックエンド化

考えた末、以下のような方針を採ることにしました。

  • 新たにフレームワークとしてRailsを採用する。
  • PHPで書いた既存のDB周りのコードは今後も使いまわす。既存DBのインターフェースを、PHPでRESTfulにWebAPI化してバックエンドとし、フロントエンドであるRailsからActiveResourceでアクセス
  • 現行のOpenPNEベースのLang-8は、DB周りをそぎ落とした上でフロントエンド化して延命。
  • 当分はフロントエンドをOpenPNE(PHP)とRailsの二頭体制にし、一部機能から徐々にRails化していく。

図にすると以下のような感じ。


Apache/mod_proxy_balancerによるロードバランサーが、URLを見てどちらかのフロントエンドにリクエストを投げる。フロントエンドは内部WebAPIを利用して、HTTPを使ってバックエンドに問い合わせ、JSONで戻り値を受け取る。それをパースしてViewで表示って感じです。

こういったデザインパターンの決定に当たっては、以下のサイトに影響を受けました。

以上のデザインを採用することで、

  • Lang-8でとりわけ負荷が大きいメンバーテーブルや日記テーブルへのクエリは、PHP上でSQLを直接書き、WebAPIインターフェースでカプセル化
  • 特定の場面でしか利用されないテーブルは、開発効率を優先してフレームワークのO/Rマッパまかせ

といったすみ分けができるようになりました。

Rails戦闘員増派

デザインは決まったけれどRailsのことはよくわからないどうしよう、と悩んでいたところ、実装能力が半端なく高い新進気鋭のアルバイトMelvin君が、タイミングよく弊社に参加。Rubyに不慣れな自分に代わり、さくっとRailsフロントエンドのベースプラットフォームを作ってくれました。そんな感じでここ一ヶ月ほどかけてバックエンドAPIの整備と、OpenPNEのフロントエンド化改造を進めて、先週やっとこさ本番環境に投入完了。

感想

良かったところ:
 Railsが使えるようになった!これでついに俺もルビイストなんだぜ〜 :D 実際にRailsで実装した機能は今のところごく一部だけれど、今後新規機能はなるべくRailsで作っていきたい。

悪かったところ:
 内部APIコールのオーバヘッドを吸収するため、全体で1.5倍〜2倍のハードウェアリソースが必要になった。ただしこれらはスケールするので、それほど問題にはならなさげ。


2009/01/20追記:この話はWebアプリ開発における「内部APIモデル」に続きます。