なぜアプリケーションに拡張性が必要なのか?
理由の行き着くところは「コスト」と「スピード」です。クラウド以前では、必要なピーク時の性能に合わせたハードウェアの調達が行われ、一時の繁忙期を除いてはCPUやメモリ資源は使われず、余った状態であることが往々にしてありました。それはハードウェアは基本的には買取型の課金体型であること、また、調達から既存環境への組み込み、アプリケーションから資源として利用できるようになるまでに、時間もかかることが理由としてあげられます。このため、使われない資源のためにもコストが必要になり、無駄が発生していました。
アプリケーションの実行基盤としてクラウドの利用が当たり前になり、この資源調達にかかる時間が大幅に短縮されました。また、資源の利用量に応じた課金体型であることが多く、アプリケーションが優れた拡張性を備え、必要な時に必要なだけ資源を割り当ててアプリケーション全体の性能を向上できれば、無駄なコストが発生しなくなります。突発的な受容量変化にも素早く対応でき、機会損失の低減とコスト最適化に寄与します。
では、アプリケーションの性能を向上させるために、どのような手法が取られているのでしょうか?
垂直方向の拡張と水平方向の拡張
性能を拡張する方法は、大きく二つに分けられます。垂直方向への拡張(スケールアップ)と、水平方向への拡張(スケールアウト)です。スケールアップは、アプリケーションの処理をこなす単位(サーバー/インスタンス/コンテナ/プロセスなど。HerokuではDynoと呼びます)自体の性能を増強(高性能なCPUを割り当てる/メモリの割り当てを増やすなど)します。また、スケールアウトは、この単位の稼働数を増やし、分散して処理させるようにします。これらによりアプリケーション全体の性能を向上させます(図1)。
クラウドにより、大規模なコンピューティング資源の調達も容易になってきたとはいえ、スケールアップによる性能向上には限界があります。優れた拡張性を備えたアプリケーションとは、スケールアウトに対応できるアプリケーションでなくてはいけません。信頼性を高めるという観点からも、アプリケーションの処理をこなす単位が複数稼働している状況が望ましくあります。
アプリケーションに求められるもの
とはいえ、どんな作り方をしたアプリケーションでも、この単位を複数稼働させれば良いかというと、そういう訳にもいきません。特に利用者固有のデータを保持し、利用者からの要求処理が、複数稼働するどの単位に割り当てられたとしても、同じデータを使って同じ結果を返せるようにする必要があります。そのためには、処理をこなす単位の外にデータを保管しておかなければなりません。この要件をふまえたアプリケーションの全体構成例が図2です。
実は、これらの考え方も含めて、Webサービスとして提供するアプリケーションが備えるべき要件をまとめたものが、連載の第1回でも触れた「The Twelve Factor App」です。
The Twelve-Factor App
Heroku創業者の1人であり初代CTOでもあるAdam Wegginsによって書かれた、Webアプリケーションを構築する際の課題と有効な手法をまとめたもの。
「The Twelve Factor App」の中から、本稿のテーマに関するファクターを少し見てみましょう。性能の拡張性に関するファクターは2つあります。
ここでは「アプリケーション」という言葉を狭い意味(処理をこなす単位)で使っています。詳細は上記のリンク先をご覧ください。
「VI.プロセス」においては「永続化する必要のあるすべてのデータは、ステートフルなバックエンドサービス(典型的にはデータベース)に格納しなければならない」と述べられています。またそれゆえに、「VIII.並行性」においては「Twelve-Factor Appプロセスの性質は、並行性を高める操作が単純かつ確実なものであることを意味する」と述べられています。
性能の拡張性に限らず、この方法論にそって開発されたアプリケーションがその真価を発揮し、アプリケーションの開発者・運用者が価値を享受できるようなさまざまな機能をHerokuは提供している、と言えます。
さて、続いては、性能を拡張するためのHerokuでの具体的な操作方法を見ていきましょう。