Неструктурированное хранилище BLOB-объектов (создание облачных приложений в реальном мире с помощью Azure)

Майк Уоссон, Рик Андерсон (, том Dykstra)

Скачивание решения ИТ-проекта или Загрузка электронной книги

Создание реальных облачных приложений с помощью электронной книги Azure основано на презентации, разработанной Скотт Гатри (. В нем объясняются 13 шаблонов и методик, которые могут помочь в успешной разработке веб-приложений для облака. Сведения о электронной книге см. в первой главе.

В предыдущей главе мы рассматривали схемы секционирования и объяснили, как приложение для устранения проблем сохраняет изображения в службе Azure Storage Blob и другие данные задач в базе данных SQL Azure. В этой главе мы подробно рассмотрим службу BLOB-объектов и покажем, как она реализована в разделе Исправление кода ИТ-проекта.

Что такое хранилище BLOB-объектов?

Служба Azure Storage Blob предоставляет способ хранения файлов в облаке. Служба BLOB-объектов имеет ряд преимуществ по сравнению с хранением файлов в локальной сетевой файловой системе:

  • Это очень масштабируемая. Одна учетная запись хранения может хранить сотни терабайт, и у вас может быть несколько учетных записей хранения. Некоторые из крупнейших клиентов Azure хранят сотни петабайтов. Microsoft SkyDrive использует хранилище BLOB-объектов.
  • Это устойчивое. Резервное копирование всех файлов, хранящихся в службе BLOB-объектов, выполняется автоматически.
  • Он обеспечивает высокий уровень доступности. Соглашение об уровне обслуживания для хранилища обещает 99,9% или 99,99% времени работы в зависимости от выбранного варианта геоизбыточности.
  • Это функция платформы как услуги (PaaS) в Azure. Это означает, что вы просто храните и извлечете файлы, платите только за фактический объем хранилища, и Azure автоматически следит за настройкой и управлением всеми виртуальными машинами и дисками, необходимыми для служеб.
  • Доступ к службе BLOB-объектов можно получить с помощью REST API или API языка программирования. Пакеты SDK доступны для .NET, Java, Ruby и других.
  • При сохранении файла в службе BLOB-объектов можно легко сделать его общедоступным через Интернет.
  • Вы можете защитить файлы в службе BLOB-объектов, чтобы они могли обращаться только к полномочным пользователям, или предоставить временный маркер доступа, который сделает их доступными только в течение ограниченного периода времени.

Когда вы создаете приложение для Azure и хотите хранить большое количество данных в локальной среде, попадают в файлы, такие как изображения, видео, документы PDF, электронные таблицы и т. д. — Рассмотрим службу BLOB-объектов.

Создание учетной записи хранения

Чтобы приступить к работе со службой BLOB-объектов, создайте учетную запись хранения в Azure. На портале щелкните создать -- Data Services -- хранилище -- Быстрое создание, а затем введите URL-адрес и расположение центра обработки данных. Расположение центра обработки данных должно быть таким же, как и веб-приложение.

Создание учетной записи хранилища

Вы выбираете основной регион, в котором вы хотите сохранить содержимое, и если вы выбрали вариант георепликации , Azure создает реплики всех данных в другом центре обработки данных в другом регионе страны. Например, если выбрать центр обработки данных "Западная часть США", то при сохранении файла он переходит в центр обработки данных "Западная часть США", но в фоновом режиме Azure также копирует его в один из других центров обработки данных США. Если в одном регионе страны происходит аварии, данные остаются безнадежными.

Azure не реплицирует данные через географические границы: Если ваше основное расположение находится в США, ваши файлы реплицируются только в другой регион в США. Если основное расположение — Австралия, файлы реплицируются только в другой центр обработки данных в Австралии.

Конечно, вы также можете создать учетную запись хранения, выполнив команды из скрипта, как было показано ранее. Ниже приведена команда Windows PowerShell для создания учетной записи хранения.

# Create a new storage account
New-AzureStorageAccount -StorageAccountName $Name -Location $Location -Verbose

После создания учетной записи хранения вы можете сразу же начать хранить файлы в службе BLOB-объектов.

Использование хранилища BLOB-объектов в приложении Fix ИТ

Приложение для устранения проблем позволяет отправлять фотографии.

Создание задачи решения ИТ

При нажатии кнопки создать Fixitприложение отправляет указанный файл изображения и сохраняет его в службе BLOB-объектов.

Настройка контейнера больших двоичных объектов

Чтобы сохранить файл в службе BLOB-объектов, необходим контейнер для его хранения. Контейнер службы BLOB-объектов соответствует папке файловой системы. Сценарии создания среды, которые мы рассматривали в главе Автоматизация всех , создают учетную запись хранения, но не создают контейнер. Поэтому целью метода CreateAndConfigure класса PhotoService является создание контейнера, если он еще не существует. Этот метод вызывается из метода Application_Start в Global. asax.

public async void CreateAndConfigureAsync()
{
    try
    {
        CloudStorageAccount storageAccount = StorageUtils.StorageAccount;

        // Create a blob client and retrieve reference to images container
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
        CloudBlobContainer container = blobClient.GetContainerReference("images");

        // Create the "images" container if it doesn't already exist.
        if (await container.CreateIfNotExistsAsync())
        {
            // Enable public access on the newly created "images" container
            await container.SetPermissionsAsync(
                new BlobContainerPermissions
                {
                    PublicAccess =
                        BlobContainerPublicAccessType.Blob
                });

            log.Information("Successfully created Blob Storage Images Container and made it public");
        }
    }
    catch (Exception ex)
    {
        log.Error(ex, "Failure to Create or Configure images container in Blob Storage Service");
    }
}

Имя учетной записи хранения и ключ доступа хранятся в коллекции appSettings файла Web. config , а код в методе StorageUtils.StorageAccount использует эти значения для создания строки подключения и установления соединения:

string account = CloudConfigurationManager.GetSetting("StorageAccountName");
string key = CloudConfigurationManager.GetSetting("StorageAccountAccessKey");
string connectionString = String.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}", account, key);
return CloudStorageAccount.Parse(connectionString);

Затем метод CreateAndConfigureAsync создает объект, представляющий службу BLOB-объектов, и объект, представляющий контейнер (папку) с именем "Images" в службе больших двоичных объектов:

CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("images");

Если контейнер с именем "Images" еще не существует, то это будет иметь значение true при первом запуске приложения для новой учетной записи хранения. код создает контейнер и устанавливает разрешения, чтобы сделать его общедоступным. (По умолчанию новые контейнеры больших двоичных объектов являются частными и доступны только пользователям, имеющим разрешение на доступ к вашей учетной записи хранения.)

if (await container.CreateIfNotExistsAsync())
{
    // Enable public access on the newly created "images" container
    await container.SetPermissionsAsync(
        new BlobContainerPermissions
        {
            PublicAccess =
                BlobContainerPublicAccessType.Blob
        });

    log.Information("Successfully created Blob Storage Images Container and made it public");
}

Хранение отправленной фотографии в хранилище BLOB-объектов

Чтобы передать и сохранить файл изображения, приложение использует интерфейс IPhotoService и реализацию интерфейса в классе PhotoService. Файл PhotoService.CS содержит весь код в приложении Fix ИТ, которое взаимодействует со службой BLOB-объектов.

Следующий метод контроллера MVC вызывается, когда пользователь нажимает кнопку создать Fixit. В этом коде photoService ссылается на экземпляр класса PhotoService, а fixittask ссылается на экземпляр класса сущностей FixItTask, в котором хранятся данные для новой задачи.

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "FixItTaskId,CreatedBy,Owner,Title,Notes,PhotoUrl,IsDone")]FixItTask fixittask, HttpPostedFileBase photo)
{
    if (ModelState.IsValid)
    {
        fixittask.CreatedBy = User.Identity.Name;
        fixittask.PhotoUrl = await photoService.UploadPhotoAsync(photo);
        await fixItRepository.CreateAsync(fixittask);
        return RedirectToAction("Success");
    }

    return View(fixittask);
}

Метод UploadPhotoAsync в классе PhotoService сохраняет отправленный файл в службе больших двоичных объектов и возвращает URL-адрес, указывающий на новый большой двоичный объект.

public async Task<string> UploadPhotoAsync(HttpPostedFileBase photoToUpload)
{            
    if (photoToUpload == null || photoToUpload.ContentLength == 0)
    {
        return null;
    }

    string fullPath = null;
    Stopwatch timespan = Stopwatch.StartNew();

    try
    {
        CloudStorageAccount storageAccount = StorageUtils.StorageAccount;

        // Create the blob client and reference the container
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
        CloudBlobContainer container = blobClient.GetContainerReference("images");

        // Create a unique name for the images we are about to upload
        string imageName = String.Format("task-photo-{0}{1}",
            Guid.NewGuid().ToString(),
            Path.GetExtension(photoToUpload.FileName));

        // Upload image to Blob Storage
        CloudBlockBlob blockBlob = container.GetBlockBlobReference(imageName);
        blockBlob.Properties.ContentType = photoToUpload.ContentType;
        await blockBlob.UploadFromStreamAsync(photoToUpload.InputStream);

        // Convert to be HTTP based URI (default storage path is HTTPS)
        var uriBuilder = new UriBuilder(blockBlob.Uri);
        uriBuilder.Scheme = "http";
        fullPath = uriBuilder.ToString();

        timespan.Stop();
        log.TraceApi("Blob Service", "PhotoService.UploadPhoto", timespan.Elapsed, "imagepath={0}", fullPath);
    }
    catch (Exception ex)
    {
        log.Error(ex, "Error upload photo blob to storage");
    }

    return fullPath;
}

Как и в методе CreateAndConfigure, код подключается к учетной записи хранения и создает объект, представляющий контейнер больших двоичных объектов "Images", за исключением случаев, когда предполагается, что контейнер уже существует.

Затем он создает уникальный идентификатор для образа, который будет отправлен, путем сцепления нового значения GUID с расширением файла:

string imageName = String.Format("task-photo-{0}{1}",
    Guid.NewGuid().ToString(),
    Path.GetExtension(photoToUpload.FileName));

Затем код использует объект контейнера больших двоичных объектов и новый уникальный идентификатор для создания объекта BLOB, устанавливает атрибут для этого объекта, указывающий тип файла, а затем использует объект большого двоичного объекта для хранения файла в хранилище BLOB-объектов.

CloudBlockBlob blockBlob = container.GetBlockBlobReference(imageName);
blockBlob.Properties.ContentType = photoToUpload.ContentType;
blockBlob.UploadFromStream(photoToUpload.InputStream);

Наконец, он получает URL-адрес, который ссылается на большой двоичный объект. Этот URL-адрес будет храниться в базе данных и может использоваться на веб-страницах исправления для вывода отправленного изображения.

fullPath = String.Format("http://{0}{1}", blockBlob.Uri.DnsSafeHost, blockBlob.Uri.AbsolutePath);

Этот URL-адрес хранится в базе данных как один из столбцов таблицы Фикситтаск.

public class FixItTask
{
    public int FixItTaskId  { get; set; }
    public string CreatedBy { get; set; }
    [Required]
    public string Owner     { get; set; }
    [Required]
    public string Title     { get; set; }
    public string Notes     { get; set; }
    public string PhotoUrl  { get; set; }
    public bool IsDone      { get; set; } 
}

Благодаря только URL-адресу в базе данных и изображениям в хранилище BLOB-приложений решение для устранения проблем сохраняет небольшие, масштабируемые и недорогие базы данных, а образы хранятся в том месте, где хранилище недорого и может обрабатывать терабайты или петабайтов. Одна учетная запись хранения может хранить сотни терабайт для исправления ИТ, и вы платите только за то, что используете. Так что вы можете начать с небольшой выплаты 9 центов на первый гигабайт и добавить дополнительные образы для копеек на каждый дополнительный гигабайт.

Отображение отправленного файла

При отображении сведений о задаче приложение для устранения проблем отображает отправленный файл изображения.

Устранение сведений о задачах ИТ с помощью фото

Чтобы отобразить изображение, все представление MVC должно содержать PhotoUrl значение в HTML-коде, отправляемом в браузер. Веб-сервер и база данных не используют циклы для показа образа. они обслуживают только несколько байтов для URL-адреса образа. В следующем коде Razor Model ссылается на экземпляр класса сущностей FixItTask.

<fieldset>
<legend>@Html.DisplayFor(model => model.Title)</legend>
<dl>
    <dt>Opened By</dt>
    <dd>@Html.DisplayFor(model => model.CreatedBy)</dd>
                <br />
    <dt>@Html.DisplayNameFor(model => model.Notes)</dt>
    <dd>@Html.DisplayFor(model => model.Notes)</dd>
                <br />
                @if(Model.PhotoUrl != null) {
        <dd><img src="@Model.PhotoUrl" title="@Model.Title" /></dd>
                }
</dl>
</fieldset>

Если взглянуть на код HTML отображаемой страницы, вы увидите URL-адрес, указывающий непосредственно на образ в хранилище BLOB-объектов, примерно так:

<fieldset>
<legend>Brush the dog again</legend>
<dl>
    <dt>Opened By</dt>
    <dd>Tom</dd>
                <br />
    <dt>Notes</dt>
    <dd>Another dog brushing task</dd>
                <br />
    <dd>
<img src="http://storageaccountname.blob.core.windows.net/images/task-photo-312dd635-ba87-4542-8b15-767032c55f4e.jpg" 
           title="Brush the dog again" />
    </dd>
</dl>
</fieldset>

Сводка

Вы увидели, как приложение для устранения проблем сохраняет изображения в службе BLOB-объектов и только URL для изображений в базе данных SQL. Использование службы BLOB-объектов позволяет хранить базу данных SQL гораздо меньше, чем в противном случае, что позволяет масштабировать до почти неограниченного числа задач и может быть выполнено без написания большого объема кода.

В учетной записи хранения можно использовать сотни терабайтов, а стоимость хранения гораздо дешевле, чем хранилище базы данных SQL, начиная с 3 центов за гигабайт в месяц и за счет небольшого объема транзакций. И помните, что вы не платите за максимальную емкость, но только за фактический объем, чтобы ваше приложение было готово к масштабированию, но вы не оплачиваете все эти дополнительные возможности.

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

Ресурсы

Дополнительные сведения см. в следующих ресурсах: