Windows Azure における"Storage利用の意味" について再考してみる。
Azureの仕事をしていると、
「Storageの使いどころ」
について、聞かれることがしばしばあります。
「Blobって、大容量向けのストレージなんですよね?どう活かせばいいのですか?」
とかなど。
私は、AzureのStorageの使用には2つの側面があると思うんです、つまり、
- クラウドだからStorageを使うべき!(前向きな側面)
- クラウドだからStorageを使わざるを得ない・・・(後ろ向きな側面)
という2つです。
両方の側面とも大事な側面だと思うのですが、1の前向きな側面ばかりが強調されることが多いため、
「いかにStorageを活用するか(できてない俺はダメ人間だ)」
的な発想になるのでしょうけど、1日に数億アクセスがあるサイトの開発者でなければ、まずは、2の後ろ向きな側面?をしっかり理解した方がいいと思うんでうよね(といいつつ、私も理解しきれてませんが・・・)。
というわけで、自分の頭の整理もかね、2の側面から、Storage利用の意味を再考してみたいと思います。
早速ですが、
なぜ、Storageを使わざるを得ないかというと、
- データの永続化
- 分散環境への対応
の2つに対応するために他なりません。
まず、データの永続化について考えてみます。
そもそもAzure内で扱われるモノ(オブジェクト、データ、リソース等)には、
- 永続化が保障されているもの(どこかに保存され消えないもの)
- 永続化が保障されていないもの(消えてしまうもの)
の2つがあります。
永続化が保障されているモノの代表がStorageやSQL Azureであり、保障されていないものの代表がアプリ内で取り扱うデータ等です。アプリ内(メモリ内)で扱ったデータ類が消えてしまうことには、開発者なら誰もが慣れていることですが、Azureでは、アプリ内のデータを(アプリが稼働するVM上の)ハードディスクに書き込んでも、アプリを終了させると、ハードディスクもろとも消えてしまいます。
Azureでは、展開されたアプリ(やそれをホストするVM)をインスタンスと呼びますが、この名が示す通り、アプリやその実行環境(ハードディスク)すべてがメモリ上に展開された一時的なインスタンスにすぎないので、アプリを閉じたり、変更したりすると基本的にデータはすべて消えてしまいます。クラスとインスタンスとの関係と同じ感じです。
では、実際に、Azureの動作を確認してみます。
Azure上に、ファイルのアップロード機能を持ったWebRoleを展開して、アプリやUploadされたファイルがいろいろなシチュエーションによってどうなるかの動作を見てみます。
サンプルアプリは、FileUploadコントロールを使った簡単なものです。
Uploadアプリの作成は、
http://code.msdn.microsoft.com/10-Windows-Azure-Web-C-ccbd7d58/
などが参考になります(肝心の保存ロジックが実装されてませんが)。
Uploadされたファイルの保存先を指定するコードはこんな感じです。
//ファイルを「カレントディレクトリ+ファイル名」で保存
FileUpload1.SaveAs(Server.MapPath("./") + "/" + FileUpload1.FileName);
アプリが実行されているカレントディレクトリ以下に、そのままのファイル名で保存されることを期待したものです。では、ここに、sample.jpgという画像ファイルをUploadしてみます。
ちなみに、sample.jpgとはこんな画像です。
たまに「Azureでは、ローカルディスクが使えない」的な記述を目にすることがありますが、そんなことはありません。永続化こそされませんが、ちゃんと、アプリが稼働するローカル環境のハードディスクにデータを書き込む(Uploadする)ことができます。
Azureのアプリは、VM上のEドライブ(E:)上に展開されます。
正確には、e:\siteroot\instance_id?\に展開(実際はE:\siteroot\0\等)されます。Upload後、RemoteDesktopでログインして確認してみます。
なお、Azure上でアプリがどのように展開されるかについては、
http://d.hatena.ne.jp/waritohutsu/20110116/1295168209
にwaritofutsu氏による素晴らしいエントリがあります。
ファイル(sample.jpg)がDefault.aspxなどを含むアプリのカレントディレクトリにUploadされているのが確認できます。
従来のホスティング環境等であれば、アプリはひとまずこれで完成です。しかし、Azureアプリとしては、留意、対応しなければならなことがいくつかあります。
さて、本題はここからです。
仮に、このアプリが本番稼働されたとしましょう。ファイルも既にアップロードされています。このような状態のアプリにおいて、データの永続化について留意しなければならない状況を考えてます。
アプリの更新(再発行)
運用中のアプリに手直しが必要になったとしましょう。手直しは、「upload」となっているボタンの文字を「アップロード」と日本語表記にするという非常に簡単なものとします。
手直しの方法はいくつか考えられますが、従来のホスティング環境等であれば、対象となるHTMLを編集し、Uploadし直すということになるでしょう。その場合、当然のことながら、Uploadしたファイルが消えてしまうことなく、手直しは完了します。
が、Azureでは、1つのファイルだけをUploadするようなことが原則としてできませんので、cspkgおよびcscfgファイルを再発行することになります。
このような場合、データはどうなるでしょうか。実際にやってみます。
VSにてボタンのTextプロパティーを変更し、発行を行いました。
アプリの発行が完了した時点で、RemoteDesktopでカレントディレクトリをのぞいてみます。
Uploadしていたsample.jpgは存在していません。
同じファイルとはいえ、完全に新しいものを発行したのですから、当然なのですが、現在のところ、アプリの更新方法は基本的に再発行しかないため、再発行で、データが消えない仕組みづくりを行う必要があります。そうしないと、アプリの更新やバグFixの度にデータが消えてしまうという事態になりかねません。
なお、RemotoDesktopでインスタンスVMにログインし、直接ファイルを編集したりするなどで、更新を行うこともできるにはできます(もちろん、手元の開発ファイルと差異が発生しますが・・・)。また、Roleが複数ある場合、Upgrade機能を利用して、対象となるRoleのみを更新することもできますが、当然、更新対象となるRoleのデータは消えてしまいます。
で、このような問題を解決するために、Storageが必要になるというわけです。
なお、ここでは、Blobにどのようにデータを保存するかについては触れません。Blobへの保存については、
http://code.msdn.microsoft.com/10-Windows-Azure-C-4817c24e
等が参考になります。
他のケースも見てみます。
StopとStart
Azure上に発行されたアプリを、Management Portal の「Stop」機能を利用して停止させ再スタートさせた場合はどうなるでしょうか。
こんなやつです。Stopを押したのち、再びStartさせます。その後、RemotoDesktopでのぞいてみます。
ファイルは見事に消えてます。データの永続化を行っていない場合、ふとした拍子にアプリをStopさせただけで、あらゆるデータがおじゃんになるというわけです。
RebootとReimage
AzureのManagement Portal には、InstanceのRebootとReimageという機能があります。
こんなやつです。
この2つの動作がファイルに与える影響についても確認しておきましょう。まず、実験の前に、再度、ファイルをアップしておきます。
sample.jpgが確認できます。この状態で、インスタンスをReboot、Reimageしてみましょう。
まず、Rebootから。
空っぽ(VMRoleとは少々動作が違いますね・・・)。
で、Reimage。
こちらも空っぽ。
RebootやReimage、あるいはそれに相当する処理は、開発者や管理者が明示的に行う機会はあまりありませんが、Azure環境上で、トラブルやVMの移動などが行われる際にバックエンドにて実行される可能性のある処理のため、あらかじめそれに備えた実装を行う必要があります。
ひとまず、データの永続化を意識しなければならないケースについては、これくらいでしょうか。
次に、分散環境への対応を見てみます。
Azureの特徴の1つとして、システムの負荷に応じてインスタンス数を動的に増やしたりすることができることです。これは非常に便利な機能ですが、データのハンドリングという観点では注意が必要です。
インスタンスを増やしてみる(分散させてみる)
では、ファイルがUploadされた状態で、インスタンスを増やしてみます。
今回は、Management Portal 上で直接cscfgファイルを編集してみます。とりあえず、Instance="1" となっているところを"2"としました。
5分くらい待つと、インスタンスが2つに増えました。
それぞれのインスタンスにRemoteDesktopでログインし、アプリのカレントドライブの状態を確認してみます。
まず、WebRole1_IN_0(もとからあったインスタンス)。
sample.jpgが確認できます。そういう意味では、cfgファイルの変更は、データの永続化には影響しないことが確認できます。
次に、WebRole1_IN_1(新規に増えたインスタンス)。
sample.jpgは確認されません。
このような状態は、何を意味するでしょうか?。
複数のインスタンスが存在する構成の場合、WebRoleに対するリクエストはAzureのロードバランサーにより、ランダム(ラウンドロビン的)にインスタンスに振り分けられます。
その時、WebRoleに、ローカルに存在するsample.jpgを参照するコードが存在していた場合、WebRole1_IN_0に振り分けられた際には画像が表示され、WebRole1_IN_1に振り分けられた際には画像が表示されないという状況が発生することになります。
このような問題を解決するためには、両インスタンスから、共通にアクセスできるエリアに画像を保存するなどの対応が必要になります。もちろん、そのエリアがStorageというわけです。
ちなみに、Azureでは、原則として、インスタンス間を跨いでリソースにアクセスすることはできないので、外部に保存する必要があります。
まとめ
Storageを使う理由は、クライドパワーをフルに活用すため!なのはもちろん、クラウド(Azure)ならではの制約を回避するためでもあります。
具体的には、
- アプリを更新したとき
- アプリをStopさせたとき
- アプリをRebootさせたとき
- アプリをReimageさせたとき
などにデータが消失してしまうことを失せぐためや、
- インスタンスを増やしたとき、変な動作にならないため
にStorageを利用する・・・ということです。