Windows Azure 体験5

| コメント(0) | トラックバック(0) このエントリーを含むはてなブックマーク

前回は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入門体験は終わりにしたい。

参考書籍

トラックバック(0)

トラックバックURL: http://www.m-tea.info/mt-tb.cgi/52

コメントする

あわせて読みたいブログパーツ

このブログ記事について

このページは、k1ha410が2009年12月25日 21:48に書いたブログ記事です。

ひとつ前のブログ記事は「Windows Azure 参考情報LINK(2009/12/25)」です。

次のブログ記事は「[速報]AzureからIronRubyを起動(疎通確認)」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。