内部WebAPIの呼び出しコスト - MVCモデルの”次”
デブサミ2009でid:secondlife氏が発表されたという資料を見てみました。
http://www.slideshare.net/hotchpotch/deb2009-1023281
はてぶをフルスクラッチでリニューアルした際に、従来のMVCモデルからさらに一歩進んで抽象化を進めたとのことで。
資料中、MVCの発展系として、MVACなる概念が提唱されているのですが、Aは「Applicaiont」??「アプリケーションレイヤの作成」という記述もあるし、たぶんApplicationのtypoですねきっと。
資料からは「データソース層」「サービス層」「アプリケーション層」の3層が「Model」「View」「Application」「Controller」にどう対応するのかよくわからなかったけど、おそらく「サービス層」を担当するのが「Application」なのでありましょう。
そして、「データソース層」のインターフェースである「サービス層」をWebAPI化すれば「データソース層」と「アプリケーション層」は、物理的に別のマシンで動かすことができるはず。。!(現状どうなのか知りませんが)。
従来のMVCモデルでは、「データソース層」を担当するModelと、「アプリケーション層」を担当するControllerしかなかったけれど、これらの間にもうひとつ「サービス層」というインターフェースをかませて、抽象化レベルを上げていく、そしてさらに「データソース層」と「アプリケーション層」を別マシンで動作させる、RPCスタイルの設計が、大規模サイトのみならず中規模サイトでも珍しくなくなる、そんな傾向が、今後進んでいく気がします。
Lang-8はまさに、この枠組みを採用しています。「サービス層」を新たにこしらえ、そのインターフェースをRESTfulにWebAPI化して、「アプリケーション層」を担うフロントエンドにリソースを提供するって感じです。
そういったRPCスタイル(「データソース層」と「アプリケーション層」を別マシンで動かす)をとる場合、どこでシステムを切り分けるか、つまり上で言う「サービス層」をフロントエンド、バックエンドのどちら側にもっていくか、が設計において鍵になるんじゃないかと。なぜなら別マシンで動作させる場合、同一マシン上で動かす場合に比べて、通信コストが圧倒的に大きいからです。例えばLang-8の場合、フロントエンドサーバから、同一サブネットにあるバックエンドサーバのAPIをコールした場合、接続オーバーヘッドだけで、1リクエストあたり平均16ms掛かっています。
Lang-8では、「サービス層」に求められるリソースの粒度と「データソース層」が提供するリソースの粒度(これはORMにもよるけれど大抵DBMSのレコード単位になるでしょうか)を比較した結果、通信コストを抑えるため「サービス層」をバックエンド側にもっていくという判断をしました。
似た話で、ネットワーク越し(HTTP)でRESTでリソースを提供する枠組みを提供してくれるもので、AmazonによるEC2及びSimpleDBというのがあります。
EC2サービスを提供するクラスターとSimpleDBを提供するクラスターはネットワーク的にかなり近い場所にあるという「噂」があったりするらしいですが、http://blog.myrss.jp/archives/2008/11/amazon_simpledb.htmlによれば、EC2からSimpleDBを呼び出した場合、
とのこと。つまり1リクエストあたり15ms。Lang-8の場合同一LAN内で16msだったから(うちで使っているのはhttpsではなくhttpだけれど)、大体同程度のコストなんだなと。
バックエンドにWebAPIを使ったアプリケーションを組む場合は、APIコールにこれくらいのコスト感をもって設計する必要があるとおもいます。