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

Рик Андерсон(Rick Anderson),Том Дайкстра (Tom Dykstra)

Скачать проект fix it или скачать электронную книгу

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

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

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

Служба BLOB-объектов службы хранилища Azure предоставляет способ хранения файлов в облаке. Служба 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. На портале щелкнитеБыстрое созданиенового -- хранилища -- служб -- данных, а затем введите URL-адрес и расположение центра обработки данных. Расположение центра обработки данных должно совпадать с расположением веб-приложения.

Создание экземпляра хранилища

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

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

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

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

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

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

Приложение Fix It позволяет отправлять фотографии.

Создание задачи

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

Настройка контейнера 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 в службе BLOB-объектов:

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

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

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 It, который взаимодействует со службой 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 классе сохраняет отправленный файл в службе BLOB-объектов и возвращает URL-адрес, указывающий на новый BLOB-объект.

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-объекта, задает атрибут для этого объекта, указывающий, какой файл это, а затем использует объект 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-адрес хранится в базе данных как один из столбцов таблицы FixItTask.

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-объектов приложение Fix It сохраняет базу данных маленькой, масштабируемой и недорогой, а образы хранятся там, где хранилище является дешевым и может обрабатывать терабайты или петабайты. В одной учетной записи хранения могут храниться сотни терабайт фотографий исправления, и вы платите только за то, что используете. Таким образом, вы можете начать с небольшой оплаты 9 центов за первый гигабайт, и добавить больше изображений за копейки за дополнительный гигабайт.

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

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

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

Чтобы отобразить изображение, все, что нужно сделать в представлении MVC, — это включить PhotoUrl значение в HTML-код, отправляемый в браузер. Веб-сервер и база данных не используют циклы для отображения изображения, а лишь несколько байтов к URL-адресу изображения. В следующем коде Model Razor ссылается на экземпляр класса сущностей 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>

Сводка

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

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

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

Ресурсы

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