Добрый день, уважаемые коллеги.
Первые пять частей цикла доступны по ссылке. В этой части цикла мы рассмотрим вопрос миграции нашего простого веб-сайта в Cloud Services (ex-Hosted Services) на примере простого приложения, которое будет использовать ролевую модель WIndows Azure, Windows Azure Service Bus и сервисы хранилища.
Давайте рассмотрим следующий сценарий: вы уже развернули ваш веб-сайт (например, стандартный веб-сайт ASP.NET MVC 4, который будет дальше рассматриваться) на Windows Azure Web Sites, однако по прошествии некоторого времени обнаружили, что от веб-сайта требуется дополнительная функциональность – необходимо, чтобы пользователь мог заходить на ваш веб-сайт и загружать изображения в собственную галерею. Подобный сценарий реализуем с помощью одной функциональности веб-сайтов, однако в списке требований также есть условие гибкой масштабируемости вашего веб-сайта. В том случае, если вы используете только Windows Azure Web Sites, вы можете масштабировать ваш веб-сайт только целиком, что является неэффективным решением – скорее всего, основная нагрузка будет приходиться на обработчиков изображений, нежели на пользовательский веб-интерфейс. Миграция веб-сайта в Cloud Services и переосмысление архитектуры с учетом ролевой модели Windows Azure Cloud Services, а также использование Windows Azure Blob Storage и Service Bus Queues поможет создать эффективную реализацию подобного сценария. В данной части цикла вы создадите облачное приложение, которое будет состоять из двух слоёв:
1) Веб-интерфейс, реализованный в виде Web-роли. На главной странице приложения пользователь сможет загружать изображения, а также просматривать уже загруженные изображения. После загрузки изображения Web-роль будет отправлять изображение в хранилище блобов в контейнер блобов, имя которого будет заранее задано для упрощения задачи, после чего класть сообщение, состоящее из ссылки на блоб с изображением в очередь Service Bus.
2) Обработчик изображений, реализованный в виде Worker-роли. Обработчик в бесконечном цикле будет опрашивать очередь Service Bus на наличие сообщений от Web-роли и в том случае, если сообщение в очереди есть, будет забирать его, получать ссылку на блоб с изображением, затем с помощью механизма копирования исходника-блоба создавать новый блоб с таким же изображением и класть его в хранилище блобов.
Настройка Cloud Services на платформе Windows Azure.
Откройте в веб-браузере windows.azure.com и войдите в систему, используя ваш Windows Live ID, к которому привязан аккаунт Windows Azure.
Создайте новый аккаунт хранилища, в котором будут храниться данные приложения. В меню Windows Azure нажмите New Storage Account. В появившемся диалоговом окне Create a New Storage Account выберите в выпадающем списке Choose a subscription вашу подписку.
В текстовом поле Enter a URL ввведите имя вашего аккаунта хранилища, например, <yourname>gallery, где <yourname> является уникальным именем. Windows Azure использует это значение для создания URL точек входа сервисов аккаунта хранилищ.
Выберите Create or choose an affinity group и нажмите в выпадающем списке Create a new affinity group.
В диалоговом окне Create a New Affinity Group введите в текстовое поле Affinity Group Name имя аффинной группы, выберите расположение (Location) в выпадающем списке и нажмите OK.Вернувшись в диалоговое окно Create a New Storage Account, нажмите Create для создания нового аккаунта хранилища. Подождите окончания процесса инициализации аккаунта и обновления «дерева»
Storage Accounts. Обратите внимание, что панель свойств Properties показывает URL, ассоциированный с каждым сервисом в аккаунте хранилища. Запишите публичное имя аккаунта хранилища – первый сегмент URL ваших точек входа.
Нажмите кнопку View, расположенную рядом с Primary access key в панели свойств Properties. В диалоговом окне View Storage Access Keys нажмите Copy to Clipboard (рядом с Primary Access Key).
Скопированное значение понадобится для конфигурирования приложения.
Создайте вычислительный сервис, который будет выполнять код вашего приложения. На левой панели нажмите Hosted Services и нажмите кнопку New Hosted Service, расположенную в меню. В диалоговом окне Create a new Hosted Service выберите вашу подписку из выпадающего списка Choose a subscription.
Введите имя сервиса в текстовое поле Enter a name for your service и укажите URL, введя соответствующее значение Enter a URL prefix for your service, например, <yourname>gallery, где <yourname> должно быть уникальным именем. Windows Azure использует это значение для создания URL точек входа в сервис. Выберите в выпадающем списке Create or choose an affinity group аффинную группу, которую вы создали ранее для аккаунта хранилища. Укажите Do not Deploy.Нажмите OKдля создания сервиса и подождите, пока не завершится процесс инициализации.Перейдите на вкладку Service Bus, Access Control & Caching. Перейдите на вкладку Service Bus. Нажмите New. В открывшемся диалоговом окне Create a new Service Namespaceвведите имя вашего Namespace(например, mytestservicebus ), выберите регион расположения и нажмите Create Namespace .. Выделите созданное пространство имён и нажмите на кнопку View на панели Propertiesв поле Default Key. Скопируйте из диалогового окна Default Keyзначения Default Issuer и Default Key.
Сервисы развертывания и хранения настроены; пространство имён Service Bus создано.
Настройка приложения ASP.NET MVC 4
Откройте Visual Studio 2012 с правами администратора.
Нажмите New Project. Выберите шаблон WebASP.NET MVC 4 Web Application (рис. 1). Назовите проект MVC4Gallery. Выберите Internet Application и снимите галочку с опции Create a unit test project. Нажмите OK. Дождитесь создания проекта.
Рис. 1. Список шаблонов веб-проектов в Visual Studio 2012
Нажмите правой кнопкой мыши на директории 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. В открывшемся диалоговом окне (рис. 3) выберите следующие сборки:
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
Рис. 3. Выбор сборок для проекта.
Откройте файл Global. asaxи добавьте в метод Application _ Start () код, приведённый ниже.
CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSettingPublisher) =>
{
var connectionString = RoleEnvironment.GetConfigurationSettingValue(configName);
configSettingPublisher(connectionString);
}
);
Щелкните правой кнопкой мыши на проекте. Выберите Add Windows Azure Cloud Service Project (рис. 4).
Рис. 4. Добавление облачного проекта в решение
Нажмите правой кнопкой мыши на Rolesв созданном проекте MVC 4 Gallery. Azure. Выберите Add. Нажмите New Worker Role Project (рис. 5).
Рис. 5. Добавление проекта для Worker-роли в решение
В Windows Azure Tools 1.7 был добавлен новый шаблон Worker-роли, уже сконфигурированный для использования Service Bus. В окне Add New Role Project выберите Worker Role with Service Bus Queue и нажмите Add (рис. 6).
Рис. 6. Добавление проекта Worker-роли, сконфигурированного для использования Service Bus Queue
Откройте файл 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;
}
}
}
}
Нажмите два раза правой кнопкой мыши на MVC 4 Galleryв Rolesоблачного проекта для того, чтобы открыть графический интерфейс администрирования Web-роли (рис. 7).
Рис. 7. Графический интерфейс управления Web-ролью
На вкладке Configurationснимите отметку с опции Enable Diagnostics. Перейдите на вкладку Settings, нажмите Add Setting и создайте новую настройку конфигурации с именем storageaccount. Укажите её тип как Connection String, после чего нажмите на кнопку с троеточием и настройте строку подключения. Необходимые данные были записаны в Части 1. Нажмите Add Settingи введите имя Microsoft.ServiceBus.ConnectionString (тип – String ), после чего вставьте в поле Valueследующую строку:
Endpoint=sb://[имяпространстваимён].servicebus.windows.net;SharedSecretIssuer=owner;SharedSecretValue=[DefaultKey]
Где наименование пространства имён для части Endpoint, Default Issuer для SharedSecretIssuer и Default Key для SharedSecretValue. Нажмите OK. Нажмите два раза правой кнопкой мыши на WorkerRoleWithSBQueue 1 в 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-ролью.
Запустите проект, нажав F 5. Проект запустится в локальном эмуляторе вычислений и запустит браузер с представлением Home / Index .
Выберите изображение и нажмите Сохранить. После загрузки изображения страница обновится.
Обратите внимание, что в данный момент показывается только одно изображение – то, которое вы загрузили. Спустя некоторое время (достаточно нескольких секунд) обновите страницу – это время понадобится обработчику изображений, чтобы опросить очередь, получить сообщение от Web-роли, загрузить блоб, создать его копию и положить новый блоб в хранилище.
Развертывание ASP.NET MVC 4 приложения на платформу Windows Azure в Cloud Services из Visual Studio 2012
Для того, чтобы развернуть приложение в Cloud Services на платформу Windows Azure, необходимо соответствующим образом настроить функциональность публикации в Visual Studio 2012 .
Нажмите правой кнопкой мыши на облачном проекте MVC 4 Gallery. Azure. Нажмите Publish.
В открывшемся диалоговом окне раскройте список под Choose your subscriptionи выберите < Manage …> (рис. 12).
Рис. 12.
В открывшемся диалоговом окне Windows Azure Cloud Service Project Management нажмите New.
Введите любое удобное вам название нового сертификата, который будет использоваться для развертывания приложения. Нажмите Ok.
Нажмите на ссылку Copy the full path. Перейдите на портал управления Windows Azure.
Перейдите на вкладку Hosted Services, Storage Accounts & CDN.
Перейдите на вкладку Management Certificates.
На вкладку Management Certificates нажмите Add Certificate.
В открывшемся диалоговом окне Add New Management Certificate нажмите Browse и вставьте в поле Имя файласкопированный из Visual Studio путь к сертификату. Нажмите Открыть. Нажмите Ok.
Перейдите на вкладку Hosted Services и скопируйте Subscription ID из панели Properties.
Перейдите в Visual Studio 2012 .
Вставьте скопированный идентификатор подписки в соответствующее поле (рис. 13). Нажмите OK.
Рис. 13.
Нажмите Close. Нажмите Next .
На странице Windows Azure Publish Settingsвы можете настроить дополнительные опции развертывания. Нажмите Publish .
Вы можете наблюдать за процессом развёртывания в представлении Windows Azure Activity Log(рис. 14).
Рис. 14. Представление Windows Azure Activity Log
Перейдите на портал управления Windows Azure на вкладку Hosted Services . Выберите развернутое приложение и нажмите на ссылку в поле DNS Nameна панели Properties, чтобы перейти на веб-сайт (рис. 15).
Рис. 15. Портал управления Windows Azure
Обратите внимание, что сайт выглядит так же, как после развёртывания его в локальный эмулятор вычислений. Это связано с тем, что в обоих случаях используется реальное хранилище Windows Azure. Добавьте новое изображение и пронаблюдайте результат.
Автор: ahriman