Certificação Microsoft 70-487: Objetivo 1.4 – Implement data storage in Windows Azure

Olá pessoal! Vamos ao primeiro (e um dos poucos) objetivo que fala de Azure na certificação de Azure, o Implement data storage in Windows Azure. Para acompanhar os objetivos já postados, clique aqui.

O primeiro tópico desse objetivo é sobre armazenamento de dados. Comparado com mecanismos de armazenamento de dados tradicionais, as soluções do Azure oferecem um suporte bem parecido com o que já existe. Mas é claro que coisas novas geram mudanças, ainda mais com um paradigma mais recente que é a nuvem. Por exemplo, acesso à internet é fundamental para que qualquer armazenamento no Azure funcione.

As opções de armazenamento de dados no Azure são: Local Storage; Blob, Table e Queue (fazendo parte do Windows Azure Storage); e SQL Database. Para o exame, é bem provável que você encontre alguma pergunta onde um cenário é dado e você deve escolher quais desses itens resolveriam o problema. Vamos às explicações básicas: quando você ler vídeo, áudio ou imagem, a pergunta está se tratando de Blob. Quando é algum dado estruturado, pode ser Table ou SQL Database, se a estrutura for relacional. Queue se trata de garantir um mecanismo de envio de mensagens em fila. Local Storage é um armazenamento temporário igual a um sistema de arquivos. Vamos nos aprofundar na implementação desses itens.

Blob Storage

A estrutura de Blob foi feita para armazenamento de dados binários, como os já mencionados vídeo, áudio e imagem. É possível também armazenar um arquivo Excel como binário sem nenhum problema. Um dos principais benefícios é que as informações são acessíveis via HTTP. Basta ter a URL e você pode acessar uma imagem, por exemplo. Os arquivos podem ter o tamanho de até 100 TB. Acho que já deu para entender o conceito, mas as coisas ideais de serem armazenadas em Blob são: imagens que podem ser vistas diretamente no browser, documentos, backups de banco de dados, vídeos e áudios.

A estrutura do Blob funciona assim: no nível mais alto está a Storage Account. Dentro dela temos Containers e, dentro dos Containers, Blobs. Há o limite de 100 TB em uma Storage Account, porém ela pode ter quantos Containers forem necessários. Pense em um Container como um subdiretório para organizar os blobs (a diferença é que Containers não podem conter Containers). Um Blob é um arquivo, sem restrição de formato. Há duas categorias de Blobs: Block (limite de 200 GB) e Page (limite de 1 TB).

Você pode acessar um Blob de duas formas. A primeira, como citado, é por uma URL HTTP. A URL tem o seguinte formato: http://.blob.core.windows.net/{container}/{blob}.

A segunda maneira é pela API do Azure SDK. Você deve adicionar uma referência ao assembly Microsoft.WindowsAzure.Storage.dll. A Storage Account é representada pela classe CloudStorageAccount. Para instanciá-la, você pode usar um de seus dois construtores. O primeiro recebe uma StorageCredentials e três URIs representando o endpoint do Blob, Queue e Storage, nessa ordem. O segundo construtor recebe uma StorageCredentials e um bool que indica se será utilizado HTTPS. Vamos ao código:

Outra maneira (bem melhor) de instanciar a classe CloudStorageAccount é usando o método estático Parse ou TryParse, que possui dois overloads: é possível usar a classe CloudConfigurationManager e chamar o método GetSetting(), que obtém a informação do arquivo .CSCFG do seu projeto Windows Azure Cloud, ou passar somente uma connection string no formato certo (<add name=”StorageConnection” connectionString=”DefaultEndpointsProtocol=https;AccountName=ACCOUNT_NAME_GOES_HERE;AccountKey=ACCOUNT_KEY_GOES_HERE” />).

Depois de instanciada a classe CloudStorageAccount, você precisa criar um CloudBlobClient e obter uma referência ao CloudBlobContainer. Lembre-se de que há dois tipos de Blobs e cada um tem seu método para obter a referência (GetBlockBlobReference e GetPageBlobReference).

Do Container é possível obter a referência para o blob desejado e salvar o conteúdo do arquivo chamando o método UploadFromStream. Há outros dois métodos para realizar o upload (UploadFromByteArray e UploadFromFile). Todos eles sobrescrevem os dados se eles já existirem e têm sua versão assíncrona (com Async no final do nome), o que é ideal para fazer o upload de Blobs grandes. É também recomendado envolver a chamada de qualquer Upload em um try/catch para tratar quaisquer erros de rede. Para fazer o download de um Blob, basta chamar o método DownloadToStream. Para deletar um Blob, há os métodos Delete e DeleteIfExists.

A criação padrão de um Container é com acesso privado. Você pode mudar a permissão chamando o método SetPermissions de um CloudBlobContainer, passando um BlobContainerPermissions com PublicAccess habilitado, por exemplo. Você pode também distribuir assinaturas de acesso temporárias com o método GetSharedAccessSignature, tanto de um Container quanto de um Blob.

Table e Queue Storage

Uma Table storage serve armazenar dados não relacionais, como os bancos de dados NoSQL (CouchDB ou MongoDB, por exemplo). Uma Queue storage serve para armazenar mensagens no esquema de fila, onde o primeiro item que entra é o primeiro a sair (FIFO, First In First Out). Queues são úteis em sistemas de entrega de mensagens ou longos processamentos.

As APIs de Table e Queue são bem parecidas com as do Blob. Você instancia a classe CloudStorageAccount, chama o método CreateCloudTableClient ou CreateCloudQueueClient e voilà. Tables e Queues são sempre privadas.

Queues são mais simples porque não há métodos de busca. Além de poder obter uma quantidade aproximada de itens na fila, basicamente há métodos para colocar e obter mensagens da fila (push-and-pop). Um aspecto interessante é que obter uma mensagem da fila não a remove completamente, só a deixa invisível por um período de tempo (1 minuto por padrão). Se seu processamento demorar mais do que esse tempo, você deve atualizar o status da mensagem como escondida para que outros processos não a vejam na fila. Após terminar seu processamento, aí sim você pode deletar a mensagem da fila.

Tables são um pouco mais interessantes pois é possível interagir com os dados. O jeito principal de obter um registro é executar uma TableOperation, mas você pode obter vários registros com uma TableQuery. Vamos a um trecho de código que adiciona um registro, obtém esse registro e o deleta. Note que a classe Record herda de TableEntity, sendo possível criar classes que representam os dados na Table.

Distribuição de Dados Usando Windows Azure Content Delivery Network (CDN)

O Windows Azure Content Delivery Network (CDN) é uma maneira de cachear conteúdos estáticos (Blobs). A ideia é usar uma localidade próxima ao client para melhorar a performance e largura de banda. Os dois principais benefícios, segundo a MSDN, são:

  • Melhorar a performance para usuários que estão longe da fonte de conteúdo e estão utilizando aplicações que necessitam de muitas requisições;
  • Escalar a distribuição para lidar melhor com uma alta carga instantânea, como um lançamento de produto.

Para usar o CDN, você deve habilitar no portal do Azure. Depois, o CDN vai funcionar assim: quando um request for feito para um Blob, ele vai redirecionar transparentemente o request para a localização mais próxima, para evitar uma viagem muito grande. O primeiro request será feito normalmente, mas os próximos serão cacheados naquela região. O tempo de expiração é importante, pois como os itens são cacheados, alguns problemas podem acontecer caso o item seja atualizado frequentemente. O que controla o tempo de expiração é a configuração Time To Live (TTL) no portal.

Para deixar um conteúdo disponível para CDN, ele deve estar em um container público e disponível para acesso anônimo. Containers públicos podem ser setados via API, como citado acima. A propriedade PublicAccess deve ser configurada como BlobContainerPublicAccessType.Container.

Com tudo configurado, basta acessar o Blob. A URL tradicional vai funcionar normalmente (http://.blob.core.windows.net/{container}/{blob}), mas uma nova URL ficará disponível pelo CDN: http://.vo.msecnd.net/{container}/{blob}.

Só relembrando: quanto mais um item for dinâmico, menos provável que ele seja um bom candidato para usar CDN, por causa do cache.

Windows Azure Caching

Cacheamento no nível do Windows Azure é bem diferente do que temos em nível de aplicação, como nesse objetivo. Esse cacheamento é role-based, ou seja, disponível em qualquer role no Windows Azure.

Há dois mecanismos: dedicated topology e co-located topology. Em uma dedicated topology, você define uma role que será especificamente designada para lidar com cache, por exemplo, toda a memória de uma Worker Role. Em um cenário de co-located topology, apenas parte dos recursos podem ser utilizado para cache. Caso você tenha 4 Worker Roles, por exemplo, pode usar 25% de cada para lidar com cache.

Existe também um serviço opcional chamado Windows Azure Shared Caching. Diferente dos anteriores, ele existe em nível de serviço, e não de role.

Lidando Com Exceções Usando Retries (SQL Database)

SQL Database, sendo um banco de dados na nuvem, tem vários benefícios como escalabilidade e facilidade de configuração. Uma desvantagem é que, com a distância física entre o servidor de aplicação e o de banco de dados, a latência aumenta, podendo causar timeouts na conexão com o banco. Como esse erro é temporário, faz sentido ter uma lógica de retentativa (retry) nas conexões com o banco de dados.

O Azure oferece um framework para implementação de lógicas de retentativa. Segue um código de retentativa em deadlocks e timeouts com ADO.NET:

Isso é tudo para esse objetivo :) Obrigado pela leitura e fique ligado no post do próximo objetivo, Create and implement a WCF Data Services service.
Até lá!