Microsoft Windows Azure

Миграция Web-сайта в Cloud Services

Разбить на страницы
Показывать лекцию целиком

Рассмотрим следующий сценарий: на Windows Azure Web Sites уже был развернут Web-сайт, однако по прошествии некоторого времени обнаружили, что от Web-сайта требуется дополнительная функциональность – необходимо, чтобы пользователь мог заходить на ваш Web-сайт и загружать изображения в собственную галерею. Подобный сценарий реализуем с помощью одной функциональности Web-сайтов, однако в списке требований также есть условие гибкой масштабируемости вашего Web-сайта. Миграция веб-сайта в Cloud Services и переосмысление архитектуры с учетом ролевой модели Windows Azure Cloud Services, а также использование Windows Azure Blob Storage и Service Bus Queues поможет создать эффективную реализацию подобного сценария. Решение будет состоять из двух компонентов:

  • Web-интерфейс, реализованный в виде Web-роли. На главной странице приложения пользователь сможет загружать изображения, а также просматривать уже загруженные изображения. После загрузки изображения Web-роль будет отправлять изображение в хранилище блобов в контейнер блобов, имя которого будет заранее задано для упрощения задачи, после чего класть сообщение, состоящее из ссылки на блоб с изображением в очередь Service Bus.
  • Обработчик изображений, реализованный в виде Worker-роли. Обработчик в бесконечном цикле будет опрашивать очередь Service Bus на наличие сообщений от Web-роли и в том случае, если сообщение в очереди есть, будет забирать его, получать ссылку на блоб с изображением, затем с помощью механизма копирования исходника-блоба создавать новый блоб с таким же изображением и класть его в хранилище блобов.
  • Для того, чтобы создать новый Cloud Service, войдите на портал управления Windows Azure.

    Создайте новый аккаунт хранилища, в котором будут храниться данные приложения. Нажмите DATA SERVICES | STORAGE | QUICK CREATE.

    (рис 12.1) Новое хранилище данных приложения в Azure

    В текстовом поле Enter a URL ввведите имя вашего аккаунта хранилища, например, <yourname>gallery, где <yourname> является уникальным именем. Windows Azure использует это значение для создания URL точек входа сервисов аккаунта хранилищ.

    Нажмите на имени созданного аккаунта хранилища. Запишите публичное имя аккаунта хранилища – первый сегмент URL ваших точек входа. Нажмите кнопку MANAGE ACCESS KEYS. В диалоговом окне Manage Access Keys нажмите Copy to Clipboard (рядом с Primary Access Key). Скопированное значение понадобится для конфигурирования приложения. Первичный Primary Access Key и вторичный ключи доступа Secondary Access Key предоставляют общий секретный ключ, который можно использовать для доступа к хранилищу. Вторичный ключ аналогичен первичному и необходим для целей резервирования.

    Создайте облачный сервис, который будет выполнять код вашего приложения, нажав NEW | COMPUTE | CLOUD SERVICE | QUICK CREATE.

    (рис 12.2) Создание облачного сервиса

    Создайте новый аккаунт Service Bus. Для этого нажмите NEW | SERVICE BUS | QUEUE | CUSTOM CREATE. Это позволит создать новый аккаунт Service Bus.

    (рис 12.3) Создание нового Service Bus

    В открывшемся окне выберите Create a new namespace и введите имя очереди.

    (рис 12.4) Создание очереди

    Нажмите на названии созданного пространства имён и нажмите на кнопку CONNECTION INFORMATION. Скопируйте из диалогового окна значения Default Issuer и Default Key.

    (рис 12.5) Информация о подключении

    Откройте Visual Studio 2012 с правами администратора.

    Нажмите New Project. Выберите шаблон Web\ASP.NET MVC 4 Web Application. Назовите проект MVC4Gallery. Выберите Internet Application и снимите галочку с опции Create a unit test project. Нажмите OK. Дождитесь создания проекта.

    Нажмите правой кнопкой мыши на директории Models. Нажмите Add | Class. В открывшемся диалоговом окне введите Image.cs и нажмите OK. Замените содержимое файла Image.cs на код, приведённый ниже.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace MVC4Gallery.Models
    {
        public class Image
        {
            public string Title{ get; set; }
            public string Link{ get; set; }
        }
    }
    

    Откройте файл Views\Home\Index.cshtml и замените его содержимое на код, приведенный ниже.

    <header>
        <div class="content-wrapper">
            <div class="float-left">
                <p class="site-title">
                    Наш первый сайт-галерея
            </div>
        </div>
    </header>
    <div id="body">
        <section class="featured">
            <div class="content-wrapper">
               <form action="/Home/Upload" method="post" enctype="multipart/form-data">
                    <label for="title">
               
                <label for="FileData">
                    Файл</label>
                <input type="file" id="FileData" name="FileData" /><br />
                <input type="submit" value="Сохранить" />
               </form>
                    Ваши изображения после "обработки":
                @foreach (var image in ViewData.Model)
                { 
       @image.Title <br />
                    <img width="100" height="100" src="@image.Link" /><br />         
       
                }
            </div>
        </section>
    
    </div>
    

    Откройте файл Controllers\HomeController.cs и замените его содержимое на код, приведенный ниже. Необходимые зависимости и библиотеки будут добавлены в следующем пункте.

    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Web;
    using System.Web.Mvc;
    using Microsoft.ServiceBus.Messaging;
    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.StorageClient;
    using MVC4Gallery.Models;
    
    namespace MvcApplication1.Controllers
    {
        public class HomeController : Controller
        {
    
            public ActionResult Index()
            {
                List<Image> images = getBlobs("ourgallery");
                return View(images);
            }
    
            [HttpPost]
            [ActionName("Upload")]
            public ActionResult Upload(string author, string title)
            {
                this.SendBlobToStorage(author);
                return RedirectToAction("Index");
            }
    
            public void SendBlobToStorage(string author)
            {
                try
                {
                    HttpPostedFileBase file = Request.Files[0];
                    CloudBlob blob = getBlobContainer("ourgallery").GetBlobReference(file.FileName);
                    NameValueCollection metadata = new NameValueCollection();
                    metadata["title"] = file.FileName;                
                    blob.UploadFromStream(file.InputStream);
                    BrokeredMessage msg = new BrokeredMessage(blob.Uri.AbsoluteUri);
                    SendBrokeredMessageToServiceBusQueue(msg);
                }
                catch (StorageClientException e)
                {
                    Console.WriteLine("Возникла ошибка во время работы с хранилищем: " + e.Message); System.Environment.Exit(1);
                }
            }
    
            public List<Image> getBlobs(string author)
            {
                CloudBlobContainer container = getBlobContainer(author);
    
                List<Image> images = new List<Image>();
                foreach (CloudBlob blob in container.ListBlobs())
                {
                    blob.FetchAttributes();
                    Image image = new Image();
                    image.Link = blob.Uri.AbsoluteUri;
                    image.Title = blob.Metadata["title"];
                    images.Add(image);
                }
                return images;
            }
    
            public static CloudBlobContainer getBlobContainer(string userId)
            {
                var account = CloudStorageAccount.FromConfigurationSetting("storageaccount");
                CloudBlobContainer container = account.CreateCloudBlobClient().GetContainerReference(userId);
                container.CreateIfNotExist();
                var permissions = container.GetPermissions();
                permissions.PublicAccess = BlobContainerPublicAccessType.Container;
                container.SetPermissions(permissions);
                return container;
            }
    
            public static void SendBrokeredMessageToServiceBusQueue(BrokeredMessage msg)
            {
                QueueDescription qd = new QueueDescription("servicebustest");
                qd.MaxSizeInMegabytes = 5120;
                qd.DefaultMessageTimeToLive = new TimeSpan(0, 1, 0);
                string connectionString =
                CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");
                QueueClient Client = QueueClient.CreateFromConnectionString(connectionString, "servicebustest");
                Client.Send(msg);
            }
    
        }
    }
    

    Нажмите правой кнопкой мыши на директории References. Выберите Add Reference. В открывшемся диалоговом окне выберите следующие сборки:

    Microsoft.WindowsAzure.StorageClient 1.7.0.0
    Microsoft.WindowsAzure.Configuration 1.7.0.0
    Microsoft.WindowsAzure.ServiceRuntime 1.7.0.0
    Microsoft.ServiceBus 1.7.0.0
    System.Runtime.Serialization 4.0.0.0
    

    Откройте файл Global.asax и добавьте в метод Application_Start() код, приведённый ниже.

    CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSettingPublisher) =>
                {
                    var connectionString = RoleEnvironment.GetConfigurationSettingValue(configName);
                    configSettingPublisher(connectionString);
                }
      );
    

    Щелкните правой кнопкой мыши на проекте. Выберите Add Windows Azure Cloud Service Project.

    Нажмите правой кнопкой мыши на Roles в созданном проекте MVC4Gallery.Azure. Выберите Add. Нажмите New Worker Role Project.

    В Windows Azure Tools 1.7 был добавлен новый шаблон Worker-роли, уже сконфигурированный для использования Service Bus. В окне Add New Role Project выберите Worker Role with Service Bus Queue и нажмите Add.

    Откройте файл WorkerRole.cs и замените его содержимое на код, приведённый ниже.

    using System;
    using System.Collections.Specialized;
    using System.Diagnostics;
    using System.Net;
    using System.Threading;
    using Microsoft.ServiceBus;
    using Microsoft.ServiceBus.Messaging;
    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.ServiceRuntime;
    using Microsoft.WindowsAzure.StorageClient;
    
    namespace WorkerRoleWithSBQueue1
    {
        public class WorkerRole : RoleEntryPoint
        {
            // The name of your queue
            const string QueueName = "servicebustest";
    
            // QueueClient is thread-safe. Recommended that you cache 
            // rather than recreating it on every request
            QueueClient Client;
            bool IsStopped;
    
            public override void Run()
            {
    
                while (!IsStopped)
                {
                    try
                    {
                        // Получение сообщения
                        BrokeredMessage receivedMessage = null;
                        receivedMessage = Client.Receive();
    
                        if (receivedMessage != null)
                        {
                            // Обработка сообщения. В данном случае изображение 
    получается из блоба, затем возвращается в том же виде, 
    но с другим именем файла.
    
                            GetBlobFromStorage("ourgallery", receivedMessage.GetBody<string>());
                            receivedMessage.Complete();
    
    
                        }
                    }
                    catch (MessagingException e)
                    {
                        if (!e.IsTransient)
                        {
                            Trace.WriteLine(e.Message);
                            throw;
                        }
    
                        Thread.Sleep(10000);
                    }
                    catch (OperationCanceledException e)
                    {
                        if (!IsStopped)
                        {
                            Trace.WriteLine(e.Message);
                            throw;
                        }
                    }
                }
            }
    
            public override bool OnStart()
            {
                CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSettingPublisher) =>
                {
                    var connectionString = RoleEnvironment.GetConfigurationSettingValue(configName);
                    configSettingPublisher(connectionString);
                }
    );
                // Определение максимального количества одновременных подключений 
                ServicePointManager.DefaultConnectionLimit = 12;
    
                // Создание очереди в том случае, если ее еще не существует 
                string sbconnectionString = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");
                var namespaceManager = NamespaceManager.CreateFromConnectionString(sbconnectionString);
                if (!namespaceManager.QueueExists(QueueName))
                {
                    namespaceManager.CreateQueue(QueueName);
                }
    
                // Инициализация подключения к очереди Service Bus 
                Client = QueueClient.CreateFromConnectionString(sbconnectionString, QueueName);
                IsStopped = false;
                return base.OnStart();
            }
    
            public override void OnStop()
            {
                // Закрытие подключения к очереди Service Bus 
                IsStopped = true;
                Client.Close();
                base.OnStop();
            }
    
            public void GetBlobFromStorage(string author, string title)
            {
                try
                {
                    CloudBlob sourceBlob = getBlobContainer("ourgallery").GetBlobReference(title);
                    CloudBlob newBlob = getBlobContainer("ourgallery").GetBlobReference(title + "small_copy");
                    newBlob.CopyFromBlob(sourceBlob);
                    NameValueCollection metadata = new NameValueCollection();
                    metadata["title"] = title + "small_copy";
    
                }
                catch (StorageClientException e)
                {
                    Console.WriteLine("Возникла ошибка: " + e.Message); System.Environment.Exit(1);
                }
            }
    
            public static CloudBlobContainer getBlobContainer(string userId)
            {
                var account = CloudStorageAccount.FromConfigurationSetting("storageaccount");
                CloudBlobContainer container = account.CreateCloudBlobClient().GetContainerReference(userId);
                container.CreateIfNotExist();
                return container;
            }
    
        }
    }
    

    Добавьте в проект MVC4Gallery файл WebRole.cs и замените его содержимое на код, приведённый ниже.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.Diagnostics;
    using Microsoft.WindowsAzure.ServiceRuntime;
    using Microsoft.WindowsAzure.StorageClient;
    
    namespace MVC4Gallery
    {
        public class WebRole : RoleEntryPoint
        {
    
            public override bool OnStart()
            {
                RoleEnvironment.Changing += RoleEnvironmentChanging;
    
                return base.OnStart();
            }
    
            private void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e)
            {
                if (e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange))
                {
                    e.Cancel = true;
                }
            }
        }
    }
    

    Нажмите два раза правой кнопкой мыши на MVC4Gallery в Roles облачного проекта для того, чтобы открыть графический интерфейс администрирования Web-роли.

    На вкладке Configuration снимите отметку с опции Enable Diagnostics. Перейдите на вкладку Settings, нажмите Add Setting и создайте новую настройку конфигурации с именем storageaccount. Укажите её тип как Connection String, после чего нажмите на кнопку с троеточием и настройте строку подключения. Необходимые данные были записаны ранее. Нажмите Add Setting и введите имя Microsoft.ServiceBus.ConnectionString (тип – String), после чего вставьте в поле Value следующую строку:

    Endpoint=sb://[имяпространстваимён].servicebus.windows.net;SharedSecretIssuer=owner;SharedSecretValue=[DefaultKey]
    

    Где наименование пространства имён для части Endpoint, Default Issuer для SharedSecretIssuer и Default Key для SharedSecretValue.

    Нажмите OK.

    Нажмите два раза правой кнопкой мыши на WorkerRoleWithSBQueue1 в Roles облачного проекта для того, чтобы открыть графический интерфейс администрирования Worker-роли.

    На вкладке Configuration снимите отметку с опции Enable Diagnostics. Перейдите на вкладку Settings, нажмите Add Setting и создайте новую настройку конфигурации с именем storageaccount. Укажите её тип как Connection String, после чего нажмите на кнопку с троеточием и настройте строку подключения. Необходимые данные были записаны в Части 1. Нажмите OK.

    Вставьте необходимые значения в строку подключения для настройки Microsoft.ServiceBus.ConnectionString. Необходимые данные были записаны в Части 1 – наименование пространства имён для части Endpoint, Default Issuer для SharedSecretIssuer и Default Key для SharedSecretValue.

    Сохраните изменения и закройте графический интерфейс управления Worker-ролью.

    Запустите проект, нажав F5. Проект запустится в локальном эмуляторе вычислений и запустит браузер с представлением Home/Index.

    Выберите изображение и нажмите Сохранить. После загрузки изображения страница обновится.

    Обратите внимание, что в данный момент показывается только одно изображение – то, которое вы загрузили. Спустя некоторое время (достаточно нескольких секунд) обновите страницу – это время понадобится обработчику изображений, чтобы опросить очередь, получить сообщение от Web-роли, загрузить блоб, создать его копию и положить новый блоб в хранилище.

    Для того, чтобы развернуть приложение в Cloud Services на платформу Windows Azure, необходимо соответствующим образом настроить функциональность публикации в Visual Studio 2012.

    Нажмите правой кнопкой мыши на облачном проекте MVC4Gallery.Azure. Нажмите Publish. В открывшемся диалоговом окне раскройте список под Choose your subscription и выберите <Manage...>.

    (рис 12.6) Развертывание приложения

    В открывшемся диалоговом окне Windows Azure Cloud Service Project Management нажмите New.

    Введите любое удобное вам название нового сертификата, который будет использоваться для развертывания приложения. Нажмите OK.

    Перейдите на вкладку Settings. На вкладке Management Certificates нажмите Add Certificate.

    В открывшемся диалоговом окне Add New Management Certificate нажмите Browse и вставьте в поле Имя файла скопированный из Visual Studio путь к сертификату. Нажмите Открыть. Нажмите OK.

    Перейдите на вкладку Settings и скопируйте Subscription ID из свойств загруженного сертификата.

    Перейдите в Visual Studio 2012.

    Вставьте скопированный идентификатор подписки в соответствующее поле. Нажмите OK.

    (рис 12.7) Установка авторизации

    Нажмите Close. Нажмите Publish.

    Вы можете наблюдать за процессом развёртывания в представлении Windows Azure Activity Log.

    (рис 12.8) Log процесса развертывания

    Перейдите на портал управления Windows Azure на вкладку Cloud Services. Выберите развернутое приложение и нажмите на ссылку в поле DNS Name на панели Properties, чтобы перейти на веб-сайт.

    Обратите внимание, что сайт выглядит так же, как после развёртывания его в локальный эмулятор вычислений. Это связано с тем, что в обоих случаях используется реальное хранилище Windows Azure. Добавьте новое изображение и пронаблюдайте результат.

    Страницы:

    Рассмотрим следующий сценарий: на Windows Azure Web Sites уже был развернут Web-сайт, однако по прошествии некоторого времени обнаружили, что от Web-сайта требуется дополнительная функциональность – необходимо, чтобы пользователь мог заходить на ваш Web-сайт и загружать изображения в собственную галерею. Подобный сценарий реализуем с помощью одной функциональности Web-сайтов, однако в списке требований также есть условие гибкой масштабируемости вашего Web-сайта. Миграция веб-сайта в Cloud Services и переосмысление архитектуры с учетом ролевой модели Windows Azure Cloud Services, а также использование Windows Azure Blob Storage и Service Bus Queues поможет создать эффективную реализацию подобного сценария. Решение будет состоять из двух компонентов:

  • Web-интерфейс, реализованный в виде Web-роли. На главной странице приложения пользователь сможет загружать изображения, а также просматривать уже загруженные изображения. После загрузки изображения Web-роль будет отправлять изображение в хранилище блобов в контейнер блобов, имя которого будет заранее задано для упрощения задачи, после чего класть сообщение, состоящее из ссылки на блоб с изображением в очередь Service Bus.
  • Обработчик изображений, реализованный в виде Worker-роли. Обработчик в бесконечном цикле будет опрашивать очередь Service Bus на наличие сообщений от Web-роли и в том случае, если сообщение в очереди есть, будет забирать его, получать ссылку на блоб с изображением, затем с помощью механизма копирования исходника-блоба создавать новый блоб с таким же изображением и класть его в хранилище блобов.
  • Для того, чтобы создать новый Cloud Service, войдите на портал управления Windows Azure.

    Создайте новый аккаунт хранилища, в котором будут храниться данные приложения. Нажмите DATA SERVICES | STORAGE | QUICK CREATE.

    (рис 12.1) Новое хранилище данных приложения в Azure

    В текстовом поле Enter a URL ввведите имя вашего аккаунта хранилища, например, <yourname>gallery, где <yourname> является уникальным именем. Windows Azure использует это значение для создания URL точек входа сервисов аккаунта хранилищ.

    Нажмите на имени созданного аккаунта хранилища. Запишите публичное имя аккаунта хранилища – первый сегмент URL ваших точек входа. Нажмите кнопку MANAGE ACCESS KEYS. В диалоговом окне Manage Access Keys нажмите Copy to Clipboard (рядом с Primary Access Key). Скопированное значение понадобится для конфигурирования приложения. Первичный Primary Access Key и вторичный ключи доступа Secondary Access Key предоставляют общий секретный ключ, который можно использовать для доступа к хранилищу. Вторичный ключ аналогичен первичному и необходим для целей резервирования.

    Создайте облачный сервис, который будет выполнять код вашего приложения, нажав NEW | COMPUTE | CLOUD SERVICE | QUICK CREATE.

    (рис 12.2) Создание облачного сервиса

    Создайте новый аккаунт Service Bus. Для этого нажмите NEW | SERVICE BUS | QUEUE | CUSTOM CREATE. Это позволит создать новый аккаунт Service Bus.

    (рис 12.3) Создание нового Service Bus

    В открывшемся окне выберите Create a new namespace и введите имя очереди.

    (рис 12.4) Создание очереди

    Нажмите на названии созданного пространства имён и нажмите на кнопку CONNECTION INFORMATION. Скопируйте из диалогового окна значения Default Issuer и Default Key.

    (рис 12.5) Информация о подключении

    Откройте Visual Studio 2012 с правами администратора.

    Нажмите New Project. Выберите шаблон Web\ASP.NET MVC 4 Web Application. Назовите проект MVC4Gallery. Выберите Internet Application и снимите галочку с опции Create a unit test project. Нажмите OK. Дождитесь создания проекта.

    Нажмите правой кнопкой мыши на директории Models. Нажмите Add | Class. В открывшемся диалоговом окне введите Image.cs и нажмите OK. Замените содержимое файла Image.cs на код, приведённый ниже.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace MVC4Gallery.Models
    {
        public class Image
        {
            public string Title{ get; set; }
            public string Link{ get; set; }
        }
    }
    

    Откройте файл Views\Home\Index.cshtml и замените его содержимое на код, приведенный ниже.

    <header>
        <div class="content-wrapper">
            <div class="float-left">
                <p class="site-title">
                    Наш первый сайт-галерея
            </div>
        </div>
    </header>
    <div id="body">
        <section class="featured">
            <div class="content-wrapper">
               <form action="/Home/Upload" method="post" enctype="multipart/form-data">
                    <label for="title">
               
                <label for="FileData">
                    Файл</label>
                <input type="file" id="FileData" name="FileData" /><br />
                <input type="submit" value="Сохранить" />
               </form>
                    Ваши изображения после "обработки":
                @foreach (var image in ViewData.Model)
                { 
       @image.Title <br />
                    <img width="100" height="100" src="@image.Link" /><br />         
       
                }
            </div>
        </section>
    
    </div>
    

    Откройте файл Controllers\HomeController.cs и замените его содержимое на код, приведенный ниже. Необходимые зависимости и библиотеки будут добавлены в следующем пункте.

    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Web;
    using System.Web.Mvc;
    using Microsoft.ServiceBus.Messaging;
    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.StorageClient;
    using MVC4Gallery.Models;
    
    namespace MvcApplication1.Controllers
    {
        public class HomeController : Controller
        {
    
            public ActionResult Index()
            {
                List<Image> images = getBlobs("ourgallery");
                return View(images);
            }
    
            [HttpPost]
            [ActionName("Upload")]
            public ActionResult Upload(string author, string title)
            {
                this.SendBlobToStorage(author);
                return RedirectToAction("Index");
            }
    
            public void SendBlobToStorage(string author)
            {
                try
                {
                    HttpPostedFileBase file = Request.Files[0];
                    CloudBlob blob = getBlobContainer("ourgallery").GetBlobReference(file.FileName);
                    NameValueCollection metadata = new NameValueCollection();
                    metadata["title"] = file.FileName;                
                    blob.UploadFromStream(file.InputStream);
                    BrokeredMessage msg = new BrokeredMessage(blob.Uri.AbsoluteUri);
                    SendBrokeredMessageToServiceBusQueue(msg);
                }
                catch (StorageClientException e)
                {
                    Console.WriteLine("Возникла ошибка во время работы с хранилищем: " + e.Message); System.Environment.Exit(1);
                }
            }
    
            public List<Image> getBlobs(string author)
            {
                CloudBlobContainer container = getBlobContainer(author);
    
                List<Image> images = new List<Image>();
                foreach (CloudBlob blob in container.ListBlobs())
                {
                    blob.FetchAttributes();
                    Image image = new Image();
                    image.Link = blob.Uri.AbsoluteUri;
                    image.Title = blob.Metadata["title"];
                    images.Add(image);
                }
                return images;
            }
    
            public static CloudBlobContainer getBlobContainer(string userId)
            {
                var account = CloudStorageAccount.FromConfigurationSetting("storageaccount");
                CloudBlobContainer container = account.CreateCloudBlobClient().GetContainerReference(userId);
                container.CreateIfNotExist();
                var permissions = container.GetPermissions();
                permissions.PublicAccess = BlobContainerPublicAccessType.Container;
                container.SetPermissions(permissions);
                return container;
            }
    
            public static void SendBrokeredMessageToServiceBusQueue(BrokeredMessage msg)
            {
                QueueDescription qd = new QueueDescription("servicebustest");
                qd.MaxSizeInMegabytes = 5120;
                qd.DefaultMessageTimeToLive = new TimeSpan(0, 1, 0);
                string connectionString =
                CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");
                QueueClient Client = QueueClient.CreateFromConnectionString(connectionString, "servicebustest");
                Client.Send(msg);
            }
    
        }
    }
    

    Нажмите правой кнопкой мыши на директории References. Выберите Add Reference. В открывшемся диалоговом окне выберите следующие сборки:

    Microsoft.WindowsAzure.StorageClient 1.7.0.0
    Microsoft.WindowsAzure.Configuration 1.7.0.0
    Microsoft.WindowsAzure.ServiceRuntime 1.7.0.0
    Microsoft.ServiceBus 1.7.0.0
    System.Runtime.Serialization 4.0.0.0
    

    Откройте файл Global.asax и добавьте в метод Application_Start() код, приведённый ниже.

    CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSettingPublisher) =>
                {
                    var connectionString = RoleEnvironment.GetConfigurationSettingValue(configName);
                    configSettingPublisher(connectionString);
                }
      );
    

    Щелкните правой кнопкой мыши на проекте. Выберите Add Windows Azure Cloud Service Project.

    Нажмите правой кнопкой мыши на Roles в созданном проекте MVC4Gallery.Azure. Выберите Add. Нажмите New Worker Role Project.

    В Windows Azure Tools 1.7 был добавлен новый шаблон Worker-роли, уже сконфигурированный для использования Service Bus. В окне Add New Role Project выберите Worker Role with Service Bus Queue и нажмите Add.

    Откройте файл WorkerRole.cs и замените его содержимое на код, приведённый ниже.

    using System;
    using System.Collections.Specialized;
    using System.Diagnostics;
    using System.Net;
    using System.Threading;
    using Microsoft.ServiceBus;
    using Microsoft.ServiceBus.Messaging;
    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.ServiceRuntime;
    using Microsoft.WindowsAzure.StorageClient;
    
    namespace WorkerRoleWithSBQueue1
    {
        public class WorkerRole : RoleEntryPoint
        {
            // The name of your queue
            const string QueueName = "servicebustest";
    
            // QueueClient is thread-safe. Recommended that you cache 
            // rather than recreating it on every request
            QueueClient Client;
            bool IsStopped;
    
            public override void Run()
            {
    
                while (!IsStopped)
                {
                    try
                    {
                        // Получение сообщения
                        BrokeredMessage receivedMessage = null;
                        receivedMessage = Client.Receive();
    
                        if (receivedMessage != null)
                        {
                            // Обработка сообщения. В данном случае изображение 
    получается из блоба, затем возвращается в том же виде, 
    но с другим именем файла.
    
                            GetBlobFromStorage("ourgallery", receivedMessage.GetBody<string>());
                            receivedMessage.Complete();
    
    
                        }
                    }
                    catch (MessagingException e)
                    {
                        if (!e.IsTransient)
                        {
                            Trace.WriteLine(e.Message);
                            throw;
                        }
    
                        Thread.Sleep(10000);
                    }
                    catch (OperationCanceledException e)
                    {
                        if (!IsStopped)
                        {
                            Trace.WriteLine(e.Message);
                            throw;
                        }
                    }
                }
            }
    
            public override bool OnStart()
            {
                CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSettingPublisher) =>
                {
                    var connectionString = RoleEnvironment.GetConfigurationSettingValue(configName);
                    configSettingPublisher(connectionString);
                }
    );
                // Определение максимального количества одновременных подключений 
                ServicePointManager.DefaultConnectionLimit = 12;
    
                // Создание очереди в том случае, если ее еще не существует 
                string sbconnectionString = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");
                var namespaceManager = NamespaceManager.CreateFromConnectionString(sbconnectionString);
                if (!namespaceManager.QueueExists(QueueName))
                {
                    namespaceManager.CreateQueue(QueueName);
                }
    
                // Инициализация подключения к очереди Service Bus 
                Client = QueueClient.CreateFromConnectionString(sbconnectionString, QueueName);
                IsStopped = false;
                return base.OnStart();
            }
    
            public override void OnStop()
            {
                // Закрытие подключения к очереди Service Bus 
                IsStopped = true;
                Client.Close();
                base.OnStop();
            }
    
            public void GetBlobFromStorage(string author, string title)
            {
                try
                {
                    CloudBlob sourceBlob = getBlobContainer("ourgallery").GetBlobReference(title);
                    CloudBlob newBlob = getBlobContainer("ourgallery").GetBlobReference(title + "small_copy");
                    newBlob.CopyFromBlob(sourceBlob);
                    NameValueCollection metadata = new NameValueCollection();
                    metadata["title"] = title + "small_copy";
    
                }
                catch (StorageClientException e)
                {
                    Console.WriteLine("Возникла ошибка: " + e.Message); System.Environment.Exit(1);
                }
            }
    
            public static CloudBlobContainer getBlobContainer(string userId)
            {
                var account = CloudStorageAccount.FromConfigurationSetting("storageaccount");
                CloudBlobContainer container = account.CreateCloudBlobClient().GetContainerReference(userId);
                container.CreateIfNotExist();
                return container;
            }
    
        }
    }
    

    Добавьте в проект MVC4Gallery файл WebRole.cs и замените его содержимое на код, приведённый ниже.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.Diagnostics;
    using Microsoft.WindowsAzure.ServiceRuntime;
    using Microsoft.WindowsAzure.StorageClient;
    
    namespace MVC4Gallery
    {
        public class WebRole : RoleEntryPoint
        {
    
            public override bool OnStart()
            {
                RoleEnvironment.Changing += RoleEnvironmentChanging;
    
                return base.OnStart();
            }
    
            private void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e)
            {
                if (e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange))
                {
                    e.Cancel = true;
                }
            }
        }
    }
    

    Нажмите два раза правой кнопкой мыши на MVC4Gallery в Roles облачного проекта для того, чтобы открыть графический интерфейс администрирования Web-роли.

    На вкладке Configuration снимите отметку с опции Enable Diagnostics. Перейдите на вкладку Settings, нажмите Add Setting и создайте новую настройку конфигурации с именем storageaccount. Укажите её тип как Connection String, после чего нажмите на кнопку с троеточием и настройте строку подключения. Необходимые данные были записаны ранее. Нажмите Add Setting и введите имя Microsoft.ServiceBus.ConnectionString (тип – String), после чего вставьте в поле Value следующую строку:

    Endpoint=sb://[имяпространстваимён].servicebus.windows.net;SharedSecretIssuer=owner;SharedSecretValue=[DefaultKey]
    

    Где наименование пространства имён для части Endpoint, Default Issuer для SharedSecretIssuer и Default Key для SharedSecretValue.

    Нажмите OK.

    Нажмите два раза правой кнопкой мыши на WorkerRoleWithSBQueue1 в Roles облачного проекта для того, чтобы открыть графический интерфейс администрирования Worker-роли.

    На вкладке Configuration снимите отметку с опции Enable Diagnostics. Перейдите на вкладку Settings, нажмите Add Setting и создайте новую настройку конфигурации с именем storageaccount. Укажите её тип как Connection String, после чего нажмите на кнопку с троеточием и настройте строку подключения. Необходимые данные были записаны в Части 1. Нажмите OK.

    Вставьте необходимые значения в строку подключения для настройки Microsoft.ServiceBus.ConnectionString. Необходимые данные были записаны в Части 1 – наименование пространства имён для части Endpoint, Default Issuer для SharedSecretIssuer и Default Key для SharedSecretValue.

    Сохраните изменения и закройте графический интерфейс управления Worker-ролью.

    Запустите проект, нажав F5. Проект запустится в локальном эмуляторе вычислений и запустит браузер с представлением Home/Index.

    Выберите изображение и нажмите Сохранить. После загрузки изображения страница обновится.

    Обратите внимание, что в данный момент показывается только одно изображение – то, которое вы загрузили. Спустя некоторое время (достаточно нескольких секунд) обновите страницу – это время понадобится обработчику изображений, чтобы опросить очередь, получить сообщение от Web-роли, загрузить блоб, создать его копию и положить новый блоб в хранилище.

    Для того, чтобы развернуть приложение в Cloud Services на платформу Windows Azure, необходимо соответствующим образом настроить функциональность публикации в Visual Studio 2012.

    Нажмите правой кнопкой мыши на облачном проекте MVC4Gallery.Azure. Нажмите Publish. В открывшемся диалоговом окне раскройте список под Choose your subscription и выберите <Manage...>.

    (рис 12.6) Развертывание приложения

    В открывшемся диалоговом окне Windows Azure Cloud Service Project Management нажмите New.

    Введите любое удобное вам название нового сертификата, который будет использоваться для развертывания приложения. Нажмите OK.

    Перейдите на вкладку Settings. На вкладке Management Certificates нажмите Add Certificate.

    В открывшемся диалоговом окне Add New Management Certificate нажмите Browse и вставьте в поле Имя файла скопированный из Visual Studio путь к сертификату. Нажмите Открыть. Нажмите OK.

    Перейдите на вкладку Settings и скопируйте Subscription ID из свойств загруженного сертификата.

    Перейдите в Visual Studio 2012.

    Вставьте скопированный идентификатор подписки в соответствующее поле. Нажмите OK.

    (рис 12.7) Установка авторизации

    Нажмите Close. Нажмите Publish.

    Вы можете наблюдать за процессом развёртывания в представлении Windows Azure Activity Log.

    (рис 12.8) Log процесса развертывания

    Перейдите на портал управления Windows Azure на вкладку Cloud Services. Выберите развернутое приложение и нажмите на ссылку в поле DNS Name на панели Properties, чтобы перейти на веб-сайт.

    Обратите внимание, что сайт выглядит так же, как после развёртывания его в локальный эмулятор вычислений. Это связано с тем, что в обоих случаях используется реальное хранилище Windows Azure. Добавьте новое изображение и пронаблюдайте результат.

    Вернуться к учебному плану