APIs e Microsserviços

19 nov, 2010

Armazenamento facilitado com S3

Publicidade

O Amazon Simple Storage Service (S3) é um serviço disponível
publicamente para desenvolvedores de aplicativos da Web. Pode-se usá-lo para
armazenar ativos digitais, como imagens, vídeos, música e documentos. O
S3 fornece uma API RESTful para fazer a interação com o serviço de forma
programática. Aprenda como usar a biblioteca JetS3t de software livre
para usar o serviço de nuvem S3 da Amazon para armazenar e recuperar
dados.

Introduzindo nas nuvens

A nuvem é uma noção abstrata de um grupo de computadores
conectados fracamente trabalhando juntos para executar alguma tarefa ou
serviço que pareça que esteja sendo realizado por uma única entidade.

A
arquitetura nos bastidores também é abstrata: cada provedor de nuvem tem
liberdade para projetar sua oferta como achar melhor. Software as a
Service (SaaS) é um conceito relacionado, já que a nuvem oferece algum
serviço aos usuários. O modelo de nuvem potencialmente reduz os custos
dos usuários, pois não precisam comprar software e o hardware para
executá-lo o provedor do serviço já fez isso.

Pegue, por exemplo, a oferta S3 da Amazon. Como seu nome sugere, é um
serviço publicamente disponível que permite desenvolvedores da Web
armazenarem ativos digitais (como imagens, vídeos, música e documentos)
para serem usados em seus aplicativos.

Ao usar o S3, parece uma máquina
na Internet que possui uma unidade de disco rígido que contém seus
ativos digitais. Na verdade, diversas máquinas (distribuídas por uma
área geográfica) contêm os ativos digitais (ou, possivelmente, partes
deles).

A Amazon também trata de toda a complexidade de atender um
pedido de serviço para armazenar seus dados e recuperá-los. Paga-se uma
pequena taxa (em torno de 15 centavos de dólar por gigabyte por mês)
para armazenar ativos em servidores da Amazon e uma para transferir
dados para os servidores da Amazon e a partir deles.

Em vez de reinventar a roda, serviço S3 da Amazon expõe uma API RESTful,
que permite acessar o S3 vem qualquer linguagem que suporte a
comunicação através de HTTP.

O projeto JetS3t é uma biblioteca Java de
software livre que abstrai os detalhes de trabalhar com a API RESTful do
S3, expondo a AI como métodos e classes Java normais.

Sempre é melhor
gravar menos código, certo? E faz muito sentido pegar emprestado o
trabalho árduo de outra pessoa também. Como verá neste artigo, a JetS3t
torna trabalhar com S3 e a linguagem Java muito mais fácil e, no final,
muito mais eficiente.

Nascimento de uma palavra de impacto

Apesar de o termo computação em nuvem não ser nada novo (a Amazon
começou a oferecer seus serviços de nuvem em 2006), ele começou a
ganhar status de palavra de impacto em 2008, à medida que as ofertas de
nuvem da Google e da Amazon acumulavam cada vez mais publicidade.

O App Engine da Google permite que os usuários construam e hospedem
aplicativos da Web na na infraestrutura da Google.
Juntamente com o S3, os Serviços da Web da Amazon incluem o serviço da
Web de computação Elastic Cloud Compute (EC2), que facilita hosting de
aplicativos na infraestrutura da Amazon.

Outras empresas indicaram sua intenção de lutar contra a Amazon e a
Google, inclusive a
Microsoft, com seu esforço Azure, e, até mesmo, a Sun Microsystems
(cujo produto de computação em nuvem ainda não foi formalmente
introduzido no mercado ainda).
A IBM, recentemente, anunciou que está criando determinados produtos disponíveis para uso por desenvolvedores também no ambiente Amazon EC2.

S3 em um alto nível

Logicamente, o S3 é uma rede de área de armazenamento (SAN) global, que
aparece como uma super grande unidade de disco rígido onde é possível
armazenar e recuperar ativos digitais.

Tecnicamente, no entanto, a
arquitetura da Amazon é um pouco diferente. Os ativos que você opta por
armazenar e recuperar através do S3 são chamados de objetos. Objetos são armazenados em

depósitos.
É possível mapear isso em sua mente usando a analogia de unidade de
disco rígido: objetos estão para arquivos como depósitos estão para
pastas (ou diretórios). E exatamente como uma unidade de disco rígido,
objetos e depósitos podem ser localizados através de um Identificador
Uniforme de Recursos (URI).

Por exemplo, em minha unidade de disco rígido, tenho um arquivo
denominado whitepaper.pdf, que está na pasta denominada documentos em
meu diretório inicial.
Assim, o URI do arquivo .pdf é
/home/aglover/documents/whitepaper.pdf. No caso do S3, o URI é
ligeiramente diferente.

Primeiro, depósitos são somente de nível superior não é possível
aninhá-los como o faria com pastas (ou diretórios) em uma unidade de
disco rígido.

Segundo, depósitos devem seguir as regras de nomenclatura da Internet;
não podem incluir traços ao lados de pontos, nomes não devem conter
sublinhados, etc.

Por fim, como nomes de depósitos se tornam parte de um
URI público no domínio da Amazon (s3.amazonaws.com), os nomes de
depósitos devem ser exclusivos em todo o S3. (A boa notícia é que só é
possível ter 100 depósitos por conta, portanto, é improvável que haja
intrusos pegando centenas de bons nomes.)

Depósitos funcionam como a raiz de um URI no S3. Ou seja, o nome de um
depósito torna-se parte do URI que leva a um objeto no S3, por exemplo,
se eu tiver um depósito denominado agdocs e um objeto denominado
whitepaper.pdf, o URI seria
http://agdocs.s3.amazonaws.com/whitepaper.pdf.

O S3 também oferece a capacidade de especificar proprietários e
permissões para depósitos e objetos, como pode-se fazer para arquivos e
pastas em uma unidade de disco rígido. Ao definir um objeto ou um
depósito no S3, é possível especificar uma política de controle de
acesso que determine quem pode acessar seus ativos do S3 e como (por
exemplo, permissões de leitura e gravação). Assim, é possível, então,
fornecer acesso a seus objetos de diversas maneiras; usando uma API
RESTful é apenas uma delas.

Mágica do DNS

Não se preocupe muito com URLs para ativos do S3. Através da mágica do
Domain Name System (DNS) e dos registros CNAME (abreviação para nome canônico),
por exemplo, é possível mapear uma URL mais customizada para a de um
S3. Ao fazer isso, é possível ocultar essencialmente o fato de você (ou
seu aplicativo) estar dependendo do S3!

Introdução ao S3 e JetS3t

Para começar a usar o S3, é necessário ter uma conta. O S3 não é
gratuito, portanto, ao criar sua conta, é necessário fornecer à Amazon
um meio de pagamento (como um número de cartão de crédito).
Não se preocupe não há taxas de configuração; você paga apenas pelo
uso. As taxas nominais para os exemplos deste artigo custarão menos de
US$ 1.

Como parte do processo de criação de conta, também é necessário criar
algumas credenciais: uma chave de acesso e uma chave secreta (pende em
nome de usuário e senha). (Também é possível obter certificados x.509;
no entanto, eles são necessários somente se você usar a API SOAP da
Amazon.)

Assim como com qualquer informação de acesso, é imperativo manter sua
chave secreta…secreta. Se qualquer outra pessoa obter suas
credenciais e usá-las para acessar o S3, você será cobrado.
Consequentemente, o comportamento padrão toda vez que criar um depósito
ou um objeto é tornar tudo privado; você deve conceder acesso
explicitamente para o mundo externo.

Com uma chave de acesso e uma chave secreta em mãos, é possível fazer download da JetS3t e usá-la com entusiasmo ilimitado para interagir com o S3 através de sua API RESTful.

Conectar-se ao S3 de forma programática através da JetS3t é um processo em duas etapas. Primeiro, deve-se criar um objeto
AWSCredentials e, então, passá-lo em um objeto
S3Service.

O objeto AWSCredentials é bem simples. Pega suas chaves de acesso e secreta como Strings. O objeto S3Service
é, na verdade, um tipo de interface. Como o S3 oferece uma API RESTful e
uma API SOAP, a biblioteca JetS3t oferece dois tipos de implementação: RestS3Service e SoapS3Service.
Para os propósitos deste artigo (e, na verdade, na maioria, se não em
todas as suas empreitadas no S3), a simplicidade da API RESTful a torna
uma boa opção.

Criar uma instância RestS3Service conectada é simples, conforme mostrado na Lista 1:

Lista 1. Criando uma instância de RestS3Service

def awsAccessKey = "blahblah"
def awsSecretKey = "blah-blah"
def awsCredentials = new AWSCredentials(awsAccessKey, awsSecretKey)

def s3Service = new RestS3Service(awsCredentials)

Agora, você está pronto para fazer algo interessante: criar um depósito,
digamos, incluir um filme nele e, então, obter uma URL especial de
tempo limitado de disponibilidade. Na verdade, isso parece um processo
de negócios, certo? É um processo de negócios associado à liberação de
um ativo limitado, como um filme.

Criando um depósito

Para meu negócio de filmes imaginário, vou criar um depósito denominado bc50i. Com
JetS3t, o processo é simples. Através do tipo S3Service, há algumas opções. Prefiro usar a chamada

getOrCreateBucket, mostrada na Lista 2. Como o nome sugere, chamar esse método retorna
uma instância do depósito (representado por uma instância do tipo

S3Bucket) ou cria o depósito no S3.

Lista 2. Criando um depósito em um servidor do S3

def bucket = s3Service.getOrCreateBucket("bc50i")

Não deixe meus exemplos de código simples te enganarem. A biblioteca
JetS3t é bem extensa. Por exemplo, é possível apurar rapidamente quantos
depósitos você possui, simplesmente perguntando a uma instância de um S3Service através da chamada listAllBuckets. Esse método retorna uma array de instâncias S3Bucket.

Com qualquer instância de um depósito, é possível solicitar seu nome e
data de criação. Mais importante ainda, é possível controlar as
permissões associadas a ele através do tipo AccessControlList da JetS3t. Por exemplo, posso pegar uma instância de meu depósito bc50i
e disponibilizá-la publicamente para leitura e gravação, conforme
mostrado na Lista 3.

Lista 3. Alterando a lista de controle de acesso de um depósito

def bucket.acl = AccessControlList.REST_CANNED_PUBLIC_READ_WRITE

É claro que, através da API, você está livre para remover os depósitos
também. A Amazon permite até que você especifique em quais áreas
geográficas gostaria de criar seu depósito.

A Amazon trata da
complexidade de onde os dados reais estão armazenados, mas você pode
pressionar a Amazon para colocar seu depósito (e depois todos os objetos
dentro dele) nos Estados Unidos ou na Europa (as opções atualmente
disponíveis).

Incluindo objetos em um depósito

Criar objetos do S3 com a API da JetS3t é tão fácil quanto a manipulação
do depósito. A biblioteca também é inteligente o suficiente para cuidar
de alguns percalços de lidar com tipos de conteúdo associados a
arquivos em um depósito do S3. Por exemplo, a imagine que o filme que eu
gostaria de transferir por upload para o S3 para que clientes
visualizem por um tempo limitado seja nerfwars2.mp4.

Criar um objeto do
S3 é tão fácil quanto criar um tipo java.io.File normal e associar o tipo S3Object a um depósito, como eu fiz na Lista 4:

Lista 4. Criando um objeto do S3

def s3obj = new S3Object(bucket, new File("/path/to/nerfwars2.mp4"))

Quando tiver um S3Object inicializado com um arquivo e um depósito, tido que precisa ser feito é transferi-lo por upload através do método putObject, conforme mostrado na Lista 5:

Lista 5. Fazer upload do filme É Muito Fácil

s3Service.putObject(bucket, s3obj)

Como o código da Lista 5, você acabou. O filme agora está nos servidores
da Amazon e a chave para o filme é seu nome. Você poderia, é claro,
substituir o nome caso precise dar outro nome ao objeto.

Na verdade, a
API da JetS3t (e, por relação, a API RESTful do Amazon S3) expõe um
pouco mais de informações quando os objetos são criados. Como se sabe,
também é possível fornecer listas de controle de acesso. Qualquer objeto
no S3 é capaz de conter metadados adicionais, que a API permite criar. É
possível consultar posteriormente qualquer objeto através da API do S3
(e, por derivação, da JetS3t) para obter esses metadados.

Criando URLs para objetos

Neste ponto, minha instância do S3 possui um depósito com um filme
dentro dele. Na verdade, meu filme pode ser localizado neste URI:
http://bc50i.s3.amazonaws.com/nerfwars2.mp4. No entanto, nenhuma outra
pessoa pode chegar a ele. (E, nesse caso, eu posso acessá-lo somente de
forma programática, pois os controles de acesso padrão associados a tudo
estão configurados para recusar qualquer acesso não credenciado a ele.)

Meu objetivo é fornecer a clientes selecionados uma maneira de ver o
novo filme (por um tempo limitado) até que eu esteja pronto para começar
a cobrar pelo acesso (o que o S3 também pode facilitar).

A Figura 1 mostra o controle de acesso padrão em ação. O documento
XML retornado (e exibido conforme necessário em meu navegador) está me
informando que o acesso foi recusado ao ativo que eu estava tentando
acessar (http://bc50i.s3.amazonaws.com/nerfwars2.mp4).

Figura 1. Segurança da Amazon em ação

Criar uma URL pública é um recurso útil exposto pelo S3. Na verdade,
com o S3, é possível criar uma URL pública que é válida somente por um
período de tempo (por exemplo, 24 horas). Para o filme que acabei de
armazenar nos servidores do S3, vou criar uma URL que seja válida por 48
horas. Depois, fornecerei essa URL a clientes selecionados ara que
possam fazer download do filme e assisti-lo quando quiserem (desde que
tenham feito download do mesmo em dois dias).

Para criar uma URL sensível ao tempo para um objeto do S3, é possível usar o método createSignedGetUrl da JetS3t, que é um método estático do tipo S3Service.

Inclui o nome de um depósito, a chave de um objeto (o nome do filme
neste caso, lembra?), algumas credenciais no formato do objeto AWSCredentials
da JetS3t) e uma data de expiração. Caso saiba o nome do depósito
desejado e a chave do objeto, é possível obter rapidamente uma URL,
conforme mostrado no código Groovy da Lista 6:

Lista 6. Criando uma URL sensível ao tempo

def now = new Date()
def url = S3Service.createSignedGetUrl(
bucket.getName(), s3obj.key, awsCredentials, now + 2)

Com Groovy, posso especificar uma data 48 horas no futuro bem facilmente através da sintaxe + 2. A URL resultante será semelhante a esta (em uma única linha):

https://bc50i.s3.amazonaws.com/nerfwars2.mp4?AWSAccessKeyId=
1asd06A5MR2&Expires=1234738280&Signature=rZvk8Gkms%3D

Agora, como essa URL resultante, os pedidos do navegador serão honrados, conforme mostrado na Figura 2:

Figura 2. A URL facilita o download

Esse processo não foi super fácil? Com algumas linhas de código, criei
um ativo seguro na nuvem que pode ser transferido por download somente
com uma URL especial.

Usando o S3 para downloads sensíveis ao tempo

O S3 faz muito sentido se suas necessidades de largura da banda e
armazenamento não forem constantes. Por exemplo, imagine o modelo de
negócio que estou demonstrando um em que filmes são liberados em
épocas específicas ao longo do ano.

No modelo de armazenamento
tradicional, seria necessário comprar um monte de espaço em algum rack
em algum lugar (ou fornecer seu próprio hardware e canal levando a ele) e
mais provavelmente ver picos de downloads seguidos calmarias de
atividade relativamente baixa. Você estaria pagando, no entanto,
independentemente da demanda.

Com o S3, o modelo é atendido baseado na
demanda a empresa paga pelo armazenamento e pela largura da banda somente
quando necessário. Além disso, os recursos de segurança do S3 permitem
especificar ainda quando as pessoas podem fazer download dos vídeos e
especificar, até mesmo, quem pode fazer download dos mesmo.

Atender esses requisitos com o S3 acaba sendo bem fácil. Em um alto
nível, criar um download limitado disponível publicamente para um filme
requer quatro etapas:

  1. Conecte ao S3.
  2. Crie um depósito.
  3. Inclua o vídeo (ou objeto) desejado nesse depósito.
  4. Crie uma URL sensível ao tempo para o vídeo.

É isso!

Uma jogada inteligente

O modelo do S3 de pagar conforme o uso possui algumas vantagens
óbvias com relação ao modelo de armazenamento tradicional. Por exemplo,
para armazenar minha coleção de música em minha própria unidade de disco
rígido, preciso comprar uma digamos uma unidade de 500 GB por US$ 130
para começar.

Não tenho nem de perto 500 GB de dados para armazenar,
portanto, na essência, estou pagando aproximadamente 25 centavos de
dólar por gigabyte para capacidade desnecessária (embora razoavelmente
barata). Também devo manter meu dispositivo e pagar pela energia. Se eu
seguir a rota da Amazon, não preciso gastar US$ 130 para começar por um
ativo que ficará obsoleto. Pagarei aproximadamente 10 centavos de dólar
por gigabyte e não preciso pagar pelo gerenciamento e manutenção do
hardware de armazenamento.

Agora, imagine os mesmos benefícios em uma
escala corporativa. O Twitter, por exemplo, armazena as imagens de suas
mais de 1 milhão de contas de usuários no S3. Pagando conforme o uso, o
Twitter economiza os altos gastos de aquisição da infraestrutura de
hardware para armazenar e fornecer essas imagens, assim como custos
contínuos de mão-de-obra e peças para configurar e manter a mesma.

Os benefícios da nuvem não terminam aí. Você também ganha baixa
latência e alta disponibilidade. A presunção é que os ativos armazenados
na nuvem da Amazon estejam fisicamente localizados em todo o globo,
portanto, o conteúdo é fornecido mais rapidamente para diversos locais.

Além disso, como seus ativos são distribuídos em diversas máquinas, seus
dados permanecem altamente disponíveis caso alguma máquina (ou parte da
rede) fique indisponível.

Em suma, os benefícios, do S3 da Amazon são simples: baixo custo,
alta disponibilidade e segurança.
A menos que seja um guru de SAN e goste de fazer manutenção de ativos de
hardware para armazenar itens digitais, a Amazon provavelmente faz um
melhor trabalho do que você.

Portanto, por que gastar dinheiro de cada
em hardware (que perde valor ao longo do tempo, não se esqueça) quando é
possível pegar emprestado de outra pessoa?

Recursos

Aprender

Obter produtos e tecnologias

***

artigo publicado originalmente no developerWorks Brasil, por Andrew Glover


Andrew Glover é presidente da Stelligent Incorporated,
que ajuda as empresas a adotar estratégias de teste de desenvolvedor e
técnicas de integração contínua que permitem que equipes entreguem o
software com mais rapidez. Consulte o blog do Andy para obter uma lista de suas publicações