前回はTABLEについて書いてみた。今回はQUEUEについて書いてみる。
前回同様書籍をベースにいろいろと挑戦してる。書籍を元に記載しているので、若干説明足らずである。その辺は、ご了承いただきたい。
ただ、今回は非常に順調に進んだのでうれしい。
Queue
Azure Storage は次の3つがあるようである
- Table
- Blob
- Queue
今回は「Queue」について挑戦してみた。
Queueとは?
一般的なキュー等については、 以前のBLOG記事 に記載した。
しかし、Azureのキューは必ずFIFOではないようである。 また、Azure StorageのQueueの説明に MSMQ(Microsoft Message Queuing)みたいなものと 説明があった。実際に MSMQを知らないので、こちらも勉強が必要だ。
登場したクラス
-
メッセージ
CloudQueueMessageはキューに詰め込むメッセージクラスであり、文字列またはバイト列を含む。 -
キュー
CloudQueueは、ロール間の通信路を示すクラスである
実装
- キューの生成
static CloudQueue GetQueue()
{
var account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
var client = account.CreateCloudQueueClient();
var queue = client.GetQueueReference("thumbnailsqueue");
return queue;
}
protected void CreqteQueue()
{
GetQueue().CreateIfNotExist();
}
以上のようにして、以下のPage_Initなどでキューを生成した
void Page_Init(object sender, EventArgs e)
{
CreateBlob();
CreqteQueue();
}
- キューへの追加
var uniqBlobName = string.Format("img_{0}_{1}.jpg",
DateTime.UtcNow.ToString("yyyyMMddHHmmss"),
Guid.NewGuid().ToString());
var container = blobStorage.GetContainerReference(@"photo");
var block = container.GetBlockBlobReference(uniqBlobName);
var s = Converter.ConvertToAsciiOnlyString(TitleTextBox.Text);
block.Metadata["title"] = Converter.ConvertToAsciiOnlyString(TitleTextBox.Text);
block.UploadFromStream(FileUpload1.FileContent);
var queue = GetQueue();
var message = new CloudQueueMessage(uniqBlobName);
queue.AddMessage(message);
上記のようにして、BLOBに追加した後、キューをGetQueue()で取得し、 そのキューにCloudQueueMessageのインスタンスを追加した。 なおCloudQueueMessageには、uniqBlobNameを渡した。
-
キューからメッセージの取得
ワーカーロールを作成し、その中でキューの取得を行った。
OnStart で RoleEnvironment.Changing += RoleEnvironmentChanging;
のコメントアウトとRoleEnvironmentChangingのコメントアウト。
あと#region Setup CloudStorageAccount Configuration Setting Publisherから#endregion
までを追加
public override bool OnStart()
{
// Set the maximum number of concurrent connections
ServicePointManager.DefaultConnectionLimit = 12;
DiagnosticMonitor.Start("DiagnosticsConnectionString");
// For information on handling configuration changes
// see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
//RoleEnvironment.Changing += RoleEnvironmentChanging;
#region Setup CloudStorageAccount Configuration Setting Publisher
// This code sets up a handler to update CloudStorageAccount instances when their corresponding
// configuration settings change in the service configuration file.
CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
{
// Provide the configSetter with the initial value
configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));
RoleEnvironment.Changed += (sender, arg) =>
{
if (arg.Changes.OfType<RoleEnvironmentConfigurationSettingChange>()
.Any((change) => (change.ConfigurationSettingName == configName)))
{
// The corresponding configuration setting has changed, propagate the value
if (!configSetter(RoleEnvironment.GetConfigurationSettingValue(configName)))
{
// In this case, the change to the storage account credentials in the
// service configuration is significant enough that the role needs to be
// recycled in order to use the latest settings. (for example, the
// endpoint has changed)
RoleEnvironment.RequestRecycle();
}
}
};
});
#endregion
return base.OnStart();
}
//private void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e)
//{
// // If a configuration setting is changing
// if (e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange))
// {
// // Set e.Cancel to true to restart this role instance
// e.Cancel = true;
// }
//}
-
初期化処理
CreateBlob();やCreqteQueue();を行いストレージの設定を行う。
さらにqueue = GetQueue();でキューを取得する
public override void Run()
{
// This is a sample worker implementation. Replace with your logic.
Trace.WriteLine("PhotList_WorkerRole entry point called", "Information");
CreateBlob();
CreqteQueue();
var queue = GetQueue();
while (true)
{
Thread.Sleep(10000);
Trace.WriteLine("Working", "Information");
}
}
-
メッセージ処理
queue = GetQueue();で取得したキューからメッセージを取得し処理をする
while (true)
{
Thread.Sleep(10000);
Trace.WriteLine("Working", "Information");
var message = queue.GetMessage();
if (message != null)
{
try
{
var name = message.AsString;
System.Diagnostics.Trace.TraceInformation(string.Format("{0}", name));
var container = blobStorage.GetContainerReference("photo");
var imageBlob = container.GetBlobReference(name);
var stream = new System.IO.MemoryStream();
imageBlob.DownloadToStream(stream);
var thumbnailStream = CreateThumbnail(stream);
var thumbnailContainer = blobStorage.GetContainerReference("thumbnail");
var thumbnailBlob = thumbnailContainer.GetBlobReference(name );
thumbnailBlob.UploadFromStream(thumbnailStream);
}
catch
{
}
finally
{
queue.DeleteMessage(message);
}
}
}
処理が終わったらqueue.DeleteMessage(message);を行い、キューからメッセージを削除する。 これを行わないと、キューからメッセージが削除されず、再起動したときなどは再度配信される。
-
BLOB一覧の取得
サムネールが存在したら、サムネールのURL、もし存在しなければ本来のイメージのURLを取得する
コードを書いてみた。
private Uri GetUrl(CloudBlob blob)
{
var container = blobStorage.GetContainerReference(@"thumbnail");
var filename = System.IO.Path.GetFileName(blob.Uri.AbsolutePath);
var thumbnailBlob = container.GetBlobReference(filename);
var isExist = container.ListBlobs().ToList().Find(item => { return (System.IO.Path.GetFileName(item.Uri.AbsolutePath) == filename); });
if (isExist != null)
{
return thumbnailBlob.Uri;
}
return blob.Uri;
}
はまった点
基本的に、はまるポイントは少なく、すんなりといった。
ちょっとあっけなかった。
さいごに
とりあえず、キューを用いてバッググラウンドでサムネール作成処理ができるようになった。
この後は、再度デプロイして、このAzure入門体験は終わりにしたい。


コメントする