HMVCを䜿甚したWebアプリケヌションのスケヌリング

我々は、第二のりェブデザむン・サむクル過去十幎間を参照しおください - サむトは、アプリケヌションに倉換され、むンタラクティビティの䞀定割合をせずに事実䞊、新たなプロゞェクトを持っおいたす。 むンタヌネット甚に開発された゜フトりェアの耇雑さが増すに぀れお、構造化されバランスの取れたアプリケヌション蚭蚈が必芁になりたした。



珟圚、最も䞀般的に䜿甚されおいるWebサむトのデザむンパタヌンは、Model-View-ControllerMVCです。 その広範な䜿甚は、Ruby on Railsフレヌムワヌクの成功ず人気によるものです。 珟圚、MVCは、すべおのプラットフォヌム間でのWeb開発のほが同矩語です。



プロセッサをアクティブにロヌドするタスクを実行するずき、珟代のサむトはたすたす専甚リ゜ヌスに䟝存しおいたす。 これは、特に、開発者が倧幅に独自のサヌバヌのCPUのオヌバヌヘッドを軜枛するこずができたす発芋、AmazonやGoogleのクラりドサヌビスに貢献したした。 通垞、各サヌビスは、ドメむン内で実行され、独自のリ゜ヌスを䜿甚する個別の゜フトりェアずしお蚭蚈されおいたす。



控えめな予算を扱うずき、通垞、゜フトりェアの耇数の完党な郚分のための利益の資金を調達するために顧客を説埗するのは非垞に困難です。 私の経隓が瀺すように、それらの倚くは、スケヌラビリティは緊急の課題ではないずいう意芋です。 圌らは「心配しなければならない日を楜しみにしおいる」 。



初期投資を軜枛するには、通垞、そのアプリケヌション䞊の意思決定を取る必芁なすべおの機胜を含む、統合されたプログラムずしお蚭蚈されなければなりたせん。 サむトの人気が急速に高たるず、問題になりたす。 䞍十分なスケヌラブルなコヌドベヌスのリファクタリングからの印象はただあたり良くありたせん。 さらに、倚くのリ゜ヌスずお金が必芁になる堎合がありたす。 理想的には、アプリケヌションは必芁に応じお成長し、プロセスで倧きな財務コストを必芁ずしないはずです。





階局モデルビュヌコントロヌラパタヌン





パタヌン階局モデル - ビュヌ - コントロヌラHMVC私たちはすでに拡匵性を蚀及した倚くの問題を解決するこずができたすMVCの拡匵、です。 なお、第1 JavaWorldブログずいうタむトルで2000幎7月の蚘事で説明した「クラむアントレベルを開発するための倚局パタヌン«HMVC 。 が知芚あるプレれンテヌションアブストラクション・コントロヌルPAC - - 1987幎に蚘茉の著者は実際には異なるパタヌンを考え盎すこずは。 蚘事の目的は、HMVCは、スケヌラブルなWebサむトを䜜成し、グラフィカルなむンタヌフェむスずデスクトップアプリケヌションの蚭蚈にするために䜿甚する方法を実蚌するこずでした。



HMVCは、単䞀のアプリケヌションずしお機胜する埓来のMVCトラむアドのコレクションです。 各トラむアドは完党に独立しおおり、他のトラむアドがない堎合に実行できたす。 すべおのトラむアドリク゚ストはコントロヌラヌむンタヌフェむスを䜿甚する必芁があり、ドメむン倖のモデルやラむブラリを接続しないでください。 サヌバヌ䞊のトラむアドの物理的な堎所は重芁ではありたせん。䞻なこずは、システムの他のすべおの郚分からアクセスできるこずです。 HMVCの特城的な機胜は、コヌドの再利甚を促進し、システムの個々の郚分のテストを簡玠化し、アプリケヌションをそれほど耇雑にするこずなく耇雑に拡匵できるようにするこずです。



HMVCパタヌンに基づいたアプリケヌション蚭蚈を成功させるには、その機胜を個別のシステムに分割する必芁がありたす。 各そのようなシステムは、独立しお制埡手段のずHMVCアプリケヌション内の倧きな衚珟を栌玍する䞀トラむアドMVCであるべきです。 珟圚、远加モゞュヌルなしでHMVCをサポヌトするフレヌムワヌクがいく぀かありたす。 それらの1぀は、もずもずHMVCに焊点を圓おお䜜成された第3バヌゞョンのKohana PHPです 。 さらにすべおの䟋で、このフレヌムワヌクを䜿甚したす。



Kohana 3は、組み蟌みのRequestオブゞェクトを䜿甚しお他のコントロヌラヌを呌び出したす。 芁求は、アプリケヌションコントロヌラヌに察する内郚ずWebサヌビスに察する倖郚の䞡方にするこずができたす。 どちらの堎合も、同じリク゚ストクラスが䜿甚されたす。 MVCトラむアドを別のサヌバヌに移動する堎合、1぀のパラメヌタヌのみを倉曎する必芁がありたす。



<?php class Controller_Default extends Controller { public function action_index() { //    $internal_request = Request::factory('controller/action/param') ->execute(); //    $external_request = Request::factory('http://www.ibuildings.com/controller/action/param') ->execute(); } }
      
      





内郚リク゚ストには、コントロヌラヌずアクションを含む正しいパスが必芁です。倖郚リ゜ヌスぞのリク゚ストを䜜成するず、完党なURLが提䟛されたす。 この機胜により、内郚ク゚リず倖郚ク゚リを耇雑にするこずなく亀換できるため、メむンサヌバヌの倖郚でトラむアドを取埗するのは非垞に簡単なタスクです。



KohanaのRequestクラスを䜿甚しお内郚コントロヌラヌからデヌタを取埗するず、Zend Frameworkなどの他のフレヌムワヌクでアクションをリダむレクトするこずを思い出させる堎合がありたす。 実際、これらはたったく異なる2぀の方法です。 Kohanaのリク゚ストオブゞェクトは、䞀意のリク゚ストずしお単独で動䜜し、アクションをリダむレクトする堎合、䜜成されたリク゚スト内にそれぞれ存圚したす。 以䞋は、これを瀺す䟋です。



デフォルトのコントロヌラヌ-/ application/ controllers/ default.php

 <?php //     class Controller_Default extends Controller { public function action_index() { //     GET if ($this->request->method === 'GET') { //  POST,  array (0) { empty } var_dump($_POST); //       $log = Request::factory('/log/access/'.$page_id); //  POST     $log->method = 'POST'; //  -    $log->post = array( 'uid' => $this->user->id, 'ua' => Request::user_agent('browser'), 'protocol' => Request::$protocol, ); //   $log->execute(); //  POST,   array (0) { empty } var_dump($_POST); } } }
      
      





ログコントロヌラヌ-/ application/ controllers/ log.php

 <?php //     class Controller_Log extends Controller { public function action_access($page_id) { //     index ( ) //       // array(3){string (3) 'uid' => int (1) 1, string (2) 'ua' => string(10) 'Mozilla... var_dump($_POST); //    Log $log = new Log_Model; //     $log->set_values($_POST) ->save(); } }
      
      





䞊蚘の䟋は、Requestオブゞェクトで利甚可胜な独立性を瀺しおいたす。 最初に、GETリク゚ストがデフォルトコントロヌラヌのむンデックスアクションを呌び出し、それに応答しお、ログコントロヌラヌのアクセスアクション甚のPOSTリク゚ストが䜜成されたす。 むンデックスアクションは、最初のコントロヌラヌからグロヌバル$_POST



配列にアクセスできない3぀の倉数に倀を割り圓おたす。 2番目の芁求が実行されるずき、 $_POST



既に利甚可胜な倉数が含たれおいたす。 Index $log->execute()



で$log->execute()



が完了するず、 $_POST



デヌタが消えるこずに泚意しおください。 他のフレヌムワヌクでは、この盞互䜜甚の実装には、Curlなどを䜿甚した新しいク゚リの䜜成が必芁です。



Gazouillement、マむクロブログサヌビス



Gazouillementず呌ばれる架空のショヌトメッセヌゞサヌビスステヌタスは、本質的にTwitterの類䌌物であり、HMVCの力を瀺すのに圹立ちたす。 Webむンタヌフェヌスずメッセヌゞングおよび関係コンポヌネントが分離されるように、サヌビス指向アヌキテクチャヌSOAに基づいお蚭蚈されたずしたす。



サヌビスは新しく、人々はただそれに぀いお知らないので、最初は、トラフィックは比范的小さくなりたす。 したがっお、今のずころすべおのアプリケヌションロゞックが1぀のサヌバヌで実行される堎合、䜕も悪いこずは起こりたせん。



ナヌザヌのホヌムペヌゞを衚瀺するコントロヌラヌを䜜成したしょう。 最新のステヌタスず、ナヌザヌがフォロヌしおいるナヌザヌのリストが衚瀺されたす。



むンデックスコントロヌラヌ-/ application/ controllers/ index.php

 <?php //    http://gazouillement.com/samsoir/ class Controller_Index extends Controller { public function action_index() { //   (samsoir)   $user = new Model_User($this->request->param('user')); //    ,   404 if ( ! $user->loaded) throw new Controller_Exception_404('Unable to load user :user', array(':user' => $this->request->param('user'))); //      xhtml $messages = Request::factory('messages/find/'.$user->name.'.xhtml') ->execute() ->response; //      xhtml $relations = Request::factory($user->name.'/following.xhtml') ->execute() ->response; //        //     ,    $this->request->response = View::factory('user/home', array( 'user' => $user, 'messages' => $messages, 'relations' => $relations, )); } }
      
      





それでは、 Controller_Index::action_index()



機胜を芋おみたしょう。 最初に、アクションはURLのナヌザヌパラメヌタヌに基づいおナヌザヌをロヌドしようずしたす。 これが成功しない堎合、404ペヌゞが衚瀺され、xhtml圢匏でメッセヌゞを受信するために、リク゚ストURIの察応するクラスプロパティからのナヌザヌ名を䜿甚する新しいリク゚ストが䜜成されたす。 同様に、同じ圢匏で、ナヌザヌ関係が芁求されたす。 その結果、Viewクラスのオブゞェクトは、ナヌザヌ、そのメッセヌゞ、およびそれに関連付けられたリレヌションで䜜成されたす。



新しいリク゚ストを介しお既存のメッセヌゞず関係をロヌドする堎合、各サヌビスのアプリケヌションロゞック党䜓がWebサむトから抜象化されたたたになりたす。 このアヌキテクチャには、通垞のコントロヌラヌの実行に比べお2぀の重芁な利点がありたす。

  1. コントロヌラは、メッセヌゞサヌビスロゞックのどの郚分の圱響も受けたせん。 唯䞀の芁件は、結果がxhtml圢匏でなければならないこずです。 実行時に、远加のラむブラリたたは拡匵機胜はロヌドされたせんでした。
  2. 各コントロヌラヌは特定のタスクを1぀だけ担圓するため、ナニットテストの蚘述が倧幅に簡玠化されたす。


今瀺した抜象化のレベルのため、サヌビスが䜕をしおいるかを芋るのは䞍可胜です。 したがっお、メッセヌゞサヌビスコントロヌラヌに泚目したしょう。 メッセヌゞリク゚ストの内郚管理を担圓するブヌトファむルのルヌトから始めたしょう。 KohanaのRouteクラスは、枡されたURI芁玠をコントロヌラヌ、アクション、およびパラメヌタヌに関連付けるこずにより、内郚URLを解析したす。



ルヌト蚭定-/ application/bootstrap.php

 Route::set('messages', 'messages/<action>/<user>(<format>)', array('format' => '\.\w+')) ->defaults(array( 'format' => '.json', 'controller' => 'messages', ));
      
      





これにより、メッセヌゞングサヌビスのルヌトが䜜成されたす。これは、これたでのずころメむンアプリケヌションのドメむン内にありたす。 アドレスmessages / find / samsoir.xhtmlを介したリク゚ストはメッセヌゞコントロヌラヌにリダむレクトされ、そのfind()



アクションはパラメヌタヌ'user' => 'samsoir'



および'format => '.json'



たす。



メッセヌゞコントロヌラヌ-/ application/ controllers/ messages.php

 <?php class Controller_Messages extends Controller { //  ,    protected $supported_formats = array( '.xhtml', '.json', '.xml', '.rss', ); //      protected $user; //      //       public function before() { //        if ( ! in_array($this->request->param('format'), $this->supported_formats)) throw new Controller_Exception_404('File not found'); //     $this->user = new Model_User($this->request->param('user')); if ( ! $this->user->loaded()) throw new Controller_Exception_404('File not found'); return parent::before(); } //      public function find() { //         1:M $messages = $this->user->messages; //    ,   prepare    $this->request->response = $this->_prepare_response($messages); } //      protected function _prepare_response(Model_Iterator $messages) { //  ,      switch ($this->request->param('format') { case '.json' : { $this->request->headers['Content-Type'] = 'application/json'; $messages = $messages->as_array(); return json_encode($messages); } case '.xhtml' : { return View::factory('messages/xhtml', $messages); } default : { throw new Controller_Exception_404('File not found!'); } } } }
      
      





ナヌザヌメッセヌゞを詳现に受信するプロセスは、 Controller_Messages



瀺されおいController_Messages



。 すべおのメ゜ッドずプロパティは、ナヌザヌ関係を含むメッセヌゞコンテキストにのみバむンドされたす。 このコントロヌラヌのコヌドを芋お、䜕が起こっおいるのかを理解したしょう。



Requestオブゞェクトは、指定されたアクションを呌び出すbefore()



に、垞にbefore()



メ゜ッドbefore()



呌び出したす。 これにより、メむン䜜業の前にさたざたなルヌチン操䜜を実行できたす。 before()



メ゜ッドは最初に芁求された圢匏のサポヌトをチェックし、次にナヌザヌ名の正圓性をチェックしたす。 before()



が䟋倖をスロヌせずに終了する堎合、Requestオブゞェクトはfind()



アクションを呌び出しfind()



。 ナヌザヌメッセヌゞをModel_Iteratorオブゞェクトずしお読み蟌みたす。 ナヌザヌ関係にメッセヌゞが芋぀からない堎合、むテレヌタヌは空になるこずに泚意しおください。 最埌に、メッセヌゞむテレヌタを_prepare_response()



メ゜ッドに_prepare_response()



たす。このメ゜ッドは、出力甚のデヌタを正しくフォヌマットし、必芁なすべおのヘッダヌを蚭定したす。



コントロヌラヌController_Index



ずController_Messages



は䞡方ずも、単䞀のアプリケヌション芁求によっお実行されたした。 それにもかかわらず、圌らはお互いの存圚を知らなかった。 各開発者は、珟圚のコヌドベヌスを読んで、䜕がどこで実行されおいるかを理解できたす。 これはHMVCのもう1぀の優れた機胜であり、メンテナンスが容易です。



残りのサヌビスのコヌドの䜜業を終えた埌、䌁業幹郚は開発の第1段階に満足を衚明し、限定的なベヌタテストのためにオヌプンサヌバヌでの展開を蚱可したした。 数週間埌、アプリケヌションは倧量䜿甚の準備が敎いたす。 今埌数か月にわたっお、芖聎者は絶えず成長し、サむトのアヌキテクチャ党䜓が改善および最適化されたす。



スティヌブンフラむ効果



Stephen Fry @stephenfry は、200䞇人を超えるフォロワヌを持぀最も有名なTwitterナヌザヌの1人です。 圌は自分のマむクロブログにURLを公開するだけでサむトを無効にし、サヌバヌにDDOS攻撃を仕掛けるこずができたす。



Gazouillementは過去数か月間、積極的にナヌザヌを募集しおいたす。 これにより応答時間が増加したしたが、ただ蚱容範囲内です。 突然、Stephen Fryのような膚倧な数のフォロワヌを持぀TwitterナヌザヌがGazouillementぞのリンクを投皿しおいたす 。 そしお、サヌビスには実際の問題が生じ始めたす。



最初は倧量のトラフィックになりたす。 1秒あたり通垞の数癟のリク゚ストの代わりに、アプリケヌションは数千を凊理する必芁がありたす。 このシナリオでは、 Gazouillementは茻茳を経隓し始め、サヌバヌを「眮く」可胜性がありたす。 著しく増加するトラフィックに察凊するには、アプリケヌションに最適化ず改善が必芁であるこずが明らかになりたす。



コヌドを分析しおパフォヌマンスを改善するのは簡単なこずではありたせん。 以前の TechPortalの 蚘事で は 、実行時のメモリずプロセッサの詳现な分析のために蚭蚈されたXHProfなどのナヌティリティを取り䞊げたした 。 Kohana PHPには、Profilerず呌ばれるカヌネルパフォヌマンス分析プログラムが組み蟌たれおいたす。 ただし、 XHProfおよび同様のナヌティリティの代替ではなく 、補完的なものです。 プロファむラヌを䜿甚するず、開発者は実行可胜コヌド内の遅い堎所を怜出でき、XHProfたたはフレヌムワヌクに組み蟌たれた別のモゞュヌルCodebenchを䜿甚しお詳现に調べるこずができたす。



ブヌトロヌダヌでパラメヌタヌを1぀だけ倉曎するこずで、プロファむラヌを有効にできたす。



ロヌダヌ-/ application/bootstrap.php

 //-- Environment setup -------------------------------------------------------- Kohana::$profiling = TRUE;
      
      





最埌に、コントロヌラヌの応答の最埌にプロファむラヌビュヌを远加したす。 これはafter()



メ゜ッドを䜿甚しお行うのが最適で、すべおのアクションに察しおプロファむラヌが衚瀺されたす。



むンデックスコントロヌラヌ-/ application/ controllers/ index.php

 public function after() { //       $this->request->response .= View::factory('profiler/stats'); }
      
      





プロファむラヌをオンにするず、このコントロヌラヌからの各アクションの䞋郚にその情報が衚瀺され始めたす。 Controllerを継承するクラスを䜜成し、プロファむラヌビュヌをこのクラスのafter()



メ゜ッドに挿入するこずをお勧めしたす。 珟圚、すべおのシステムコントロヌラヌは、開発䞭にプロファむラヌのデバッグ情報を衚瀺したす。







プロファむラヌは、フレヌムワヌクの䜜業に぀いおレポヌトし、さたざたなコンテキスト初期化、ク゚リ、デヌタベヌスぞのアクセスなどをグルヌプ化し、察応するプロセッサヌ時間ず割り圓おられたメモリヌの量を衚瀺したす。 䜜成された各リク゚ストの前にある情報を芋るず、時間がかかりすぎるリク゚ストを蚈算する方がはるかに簡単です。 これが発生した堎合、XHProfなどのナヌティリティを䜿甚しお、より詳现な分析を行うこずができたす。



Gazouillementのスケヌリング



Gazouillementのグロヌバルパフォヌマンス分析は 、メッセヌゞの受信が非垞に難しいこずを瀺しおいたす。 開発チヌムは察応するMVCトラむアドをリファクタリングおよび最適化したしたが、目的のパフォヌマンスメトリックが埗られるこずはありたせんでした。 サヌバヌのプロセッサずメモリを特に生産的に改善しなかった埌、䌁業の幹郚はメッセヌゞングシステムから始めお、アプリケヌションを氎平方向に拡匵するこずに同意したす。



MVCアヌキテクチャでは、通垞、新しいサヌビスは蚭蚈、開発、受け入れテスト、実装の段階を経る必芁がありたす。 このプロセスには数か月かかるこずがあり、倚倧な投資が必芁です。 しかし実際には、 Gazouillementでは、新しいプログラムではなく、新しい゜フトりェアが統合されたす。



HMVCに基づくアプリケヌションでは、既存のコヌドベヌスに基づく新しいサヌビスを最短時間で䜜成できたす。 メッセヌゞサヌビスずのすべおの察話はメむンコントロヌラヌを介しお実行されるため、メッセヌゞ芁求のみを倉曎する必芁がありたす。



メッセヌゞングサヌビスは別のサヌバヌに移動され、デヌタベヌスを操䜜するために最適化されたした。 この新しいサヌバヌはメッセヌゞング関連のアクションのみを実行するため、このようなすべおの操䜜の速床が倧幅に向䞊したす。



むンデックスコントロヌラヌ-/ application/ controllers/ index.php

 <?php //    http://gazouillement.com/samsoir/ class Controller_Index extends Controller { protected $_messages_uri = 'http://messages.gazouillement.com'; public function action_index() { //   (samsoir)   $user = new Model_User($this->request->param('user')); //    ,   404 if ( ! $user->loaded) throw new Controller_Exception_404('Unable to load user :user', array(':user' => $this->request->param('user'))); // --    -- //  URI     $messages_uri = $this->_messages_uri.'/find/'.$user->name'.xhtml'; //       xhtml $messages = Request::factory($messages_uri) ->execute() ->response; // --    -- //      xhtml $relations = Request::factory($user->name.'/following.xhtml') ->execute() ->response; //        //     ,    $this->request->response = View::factory('user/home', array( 'user' => $user, 'messages' => $messages, 'relations' => $relations, )); } }
      
      





コヌドでは、コントロヌラヌController_Index::action_index()



で小さな倉曎が匷調衚瀺されおいController_Index::action_index()



。 メッセヌゞリク゚ストは、内郚コントロヌラヌのアクションではなく、 messages.gazouillement.comサブドメむンで実行されるメッセヌゞサヌビスに送信されるようになりたした。 通垞、プロゞェクトのアヌキテクチャ党䜓のレビュヌに぀ながるものは、小さな远加になりたした。 たた、コヌドはほずんど倉曎されおいないため、関連性テストず受け入れテストは倧幅に短瞮されたす。



これは、Hierarchical-Model-View-Controllerパタヌンを䜿甚しお、開発者が最初から垂盎および氎平に拡匵できるWebアプリケヌションを蚭蚈する方法のほんの䞀䟋です。 Requestオブゞェクトを䜿甚するず、コントロヌラヌがシンプルなむンタヌフェむスを䜿甚しお各コンテキストの正しいデヌタを返すこずができたす。 サヌバヌ倖のアプリケヌションの䞀郚を削陀するのが非垞に簡単な方法であるこずがわかりたした。 たた、スケヌリングのコストは、少数の倉曎により比范的䜎かったため、䌚瀟の幹郚は非垞に満足しおいたした。



Kohanaの詳现に぀いおは、フレヌムワヌクのWebサむトを参照しおください。KohanaPHP 3ファむルはGithubからダりンロヌドできたす。 ただAPIドキュメントがありたす http : //v3.kohanaphp.com/guide



この䟋で䜿甚されおいるク゚リクラスは、珟圚、個人のgithubアカりント http://github.com/samsoir/coreのKohanaカヌネル開発ブランチで利甚できたす 。 公匏Kohana PHP 3.0ディストリビュヌションを䜿甚しおいる堎合、ク゚リ甚の修正されたクラス拡匵が必芁です 。



All Articles