Desenvolvimento em Java 2.0: Escale o Elastic Beanstalk

Escale a nuvem com o PaaS infinitamente flexível da Amazon

Para os que querem ter mais controle sobre o ambiente, mas gostam da escalabilidade plug and play do PaaS, o Beanstalk pode ser uma alternativa boa e bem-vinda ao Google App Engine. O tour guiado de Andrew Glover sobre o Beanstalk começa com um aplicativo remoto baseado em local (que foi desenvolvido usando o framework Play e MongoDB), que ele em seguida porta para o ambiente do Beanstalk. Ele descobre que configurar o Beanstalk é uma tarefa simples e compensadora, com opções e flexibilidade muito melhores que as do GAE.

Andrew Glover, Author and developer, Beacon50

Andrew GloverAndrew Glover é um desenvolvedor, autor, palestrante e empreendedor com grande interesse em behavior-driven development (BDD - Desenvolvimento Guiado por Comportamento), Continuous Integration (CI - Integração contínua) e no desenvolvimento ágil de software. É possível acompanhá-lo em seu blog.



16/Mar/2011

Quando esta série estreou, há quase dois anos, eu descrevi o Java™ Development 2.0 como um efeito que foi resultado, principalmente de duas tendências interessantes: (1) desenvolvedores que usam frameworks e ferramentas de software livre para desenvolver aplicativos de software de cima para baixo e (2) empresas que alugam — ou pegam emprestada— a infraestrutura do aplicativo necessária para gerenciar todos os níveis do ciclo de vida de desenvolvimento de software, inclusive a implementação do aplicativo.

Sobre esta série

O panorama de desenvolvimento em Java mudou radicalmente desde que a tecnologia Java emergiu. Graças a estruturas maduras de software livre e infraestruturas de implementação confiáveis de aluguel, agora é possível montar, testar, executar e manter aplicativos Java de forma rápida e barata. Nesta série, Andrew Glover explora o espectro de tecnologias e ferramentas que tornam este novo paradigma de desenvolvimento Java possível.

Anteriormente nesta série, eu abordei duas plataformas de nuvem para o desenvolvimento Web em Java: Google App Engine e Amazon EC2 (consulte Recursos). Cada plataforma representa o potencial do Java 2.0 à sua maneira. Ao passo que o GAE é uma oferta de PaaS plataforma como serviço, o EC2 está mais para uma infraestrutura como serviço (IaaS). Considere o EC2 como um ambiente virtual on demand que permite instalar praticamente qualquer coisa que você quiser. O GAE é mais seletivo e foi configurado somente para o desenvolvimento de aplicativos da Web Python e Java.

Comparado com o EC2, o GAE tem fornecido, até agora, um caminho mais fácil e rápido para o desenvolvimento de aplicativos baseado em nuvem. Entretanto, nos últimos anos, o mercado de PaaS se aqueceu. O conceito se estabeleceu, e alguns dizem que está prestes a se difundir amplamente (consulte Recursos). Portanto, o fato de a Amazon ter anunciado recentemente a sua própria plataforma de PaaS, chamada Elastic Beanstalk, não deveria ser surpresa para ninguém.

Beanstalk da Amazon

O GAE e o Beanstalk são plataformas de nuvem feitas especialmente para o desenvolvimento de aplicativos Java. Como o GAE, o Beanstalk permite implementar arquivos WAR em um ambiente amorfo e superescalável — nesse caso, desenvolvido com EC2. Entretanto, ao contrário do GAE, o Beanstalk permite customizar o ambiente de aplicativos — algo que é considerado interessante (muitas vezes com razão) para os desenvolvedores de software.

Por exemplo: ao contrário do GAE, o Beanstalk oferece controle total sobre o número de nós nos quais o seu aplicativo está hospedado, tornando a escala horizontal fácil e eficiente. Também é possível usar a biblioteca Java que você quiser — e essa é outra área na qual o GAE pode ser complicado. Em relação às tarefas de PaaS mais gerais, o Beanstalk oferece balanceamento de carga ao longo dos nós, versões dos artefatos de implementação e até mesmo acesso de terminal remoto de baixo nível a instâncias do EC2. A emissão de relatórios é integrada — portanto, é possível verificar o funcionamento e desempenho do ambiente de aplicativos em qualquer momento.


Beanstalk ou GAE?

As vantagens do Beanstalk em relação ao GAE se baseiam em modelos de serviço baseados em nuvem totalmente diferentes. Atualmente, o GAE é uma estratégia estrita de PaaS: não há muitas opções quando se segue a rota do GAE e, em alguns cenários, isso funciona. Há uma opção de armazenamento de dados (Bigtable) e um número limitado de bibliotecas Java para escolher. Por exemplo: atualmente não é possível desenvolver um aplicativo da Web baseado no Hibernate, mas isso pode mudar no futuro (consulte Recursos). Depois que o aplicativo da é implementado Web, não se tem muito controle sobre ele. Na verdade, em termos de escala de nuvem, não se tem controle nenhum. Basicamente, com o GAE, você deixa a escala a cargo da Google — e isso faz sentido, considerando o conhecimento Google nessa área. No entanto, alguns desenvolvedores e empresas querem ter mais controle sobre os aplicativos. Além disso, querem esse controle na nuvem.

A falta de proteção à privacidade de dados também é um ponto crítico para alguns. Ao desenvolver um aplicativo da Web com o GAE, você não determina onde os dados residirão. Em domínios onde os dados são reis, ou melhor, a privacidade dos dados é rainha, não é muito confortável, nem muito legal, enviar os dados para a abstração do Bigtable. Em alguns casos, o GAE é simplesmente descartado por causa disso.


Magnus e o Beanstalk

Antes de explorar o Beanstalk, preciso desenvolver um aplicativo da Web que demonstrará alguns dos seus recursos. Meu aplicativo, chamado Magnus, toma dados de local de um dispositivo remoto e os persiste em um armazenamento de dados. Considerando que milhões de dispositivos remotos são conectados simultaneamente, o Magnus precisa ter a capacidade de escalar de forma rápida e fácil caso a sua popularidade aumente explosivamente. Usarei a escala horizontal e ajustarei o Beanstalk para garantir que eu tenha todas as instâncias do aplicativo que sejam necessárias quando eu precisar delas.

Inscreva-se no AWS

Para começar a usar o Beanstalk, é necessário inscrever-se no Amazon Web Services. O Beanstalk fornece atualmente um plano grátis, mas certamente haverá um preço a pagar à medida que você escala recursos e largura da banda.

Como o desenvolvimento do aplicativo não é o tema principal deste artigo, o aplicativo será desenvolvido rapidamente. Primeiro, usarei o framework Play baseado em Java para desenvolver um terminal de REST simples no qual os dispositivos remotos postarão um documento JSON que descreve as coordenadas geográficas do dispositivo. O Play alega ser uma alternativa de pilha completa às "pilhas corporativas Java que são grandes demais". É simples colocá-lo em funcionamento rapidamente, e gosto do sistema de roteamento simples do framework. O fato de se basear em um modelo stateless agiliza o desenvolvimento de aplicativos com REST, e o Play permite conectar facilmente o meu modelo de persistência — um modelo que usa o MongoDB.

Para este aplicativo, armazenarei coordenadas de local em uma instância do MongoDB hospedada pelo MongoHQ, que é outro provedor de PaaS. Criarei um armazenamento de dados e incluirei documentos rapidamente nele por meio do HTTP. O MongoHQ cuidará do resto.

Desenvolvendo o aplicativo

Omitirei a interface da Web de administração da conta neste aplicativo. Em um cenário no "mundo real", os usuários finais criariam contas para o serviço do Magnus. Em seguida, talvez eu integrasse dados adicionais da conta ao documento JSON correspondente que descreve o local da conta. Por enquanto, a URL será suficiente para associar um local a uma conta.

Suponha que um dispositivo esteja associado à conta 12345 e que o dispositivo atualmente está localizado em Quebec, no Canadá. O documento JSON correspondente enviado para o meu aplicativo da Web ficaria parecido com a Lista 1:

Lista 1. Um documento JSON simples que descreve um local
{
 "name":"location payload",
 "latitude":"46.49",
 "longitude":"71.11",
 "timestamp":"02-02-2011 14:43"
}

Usaria uma chamada HTTP PUT para por este documento na URL a seguir, que corresponde ao local da conta:

Lista 2. Um URI com REST referente ao local de uma conta
http://some.web.address.com/location/12345

O local é o recurso no URI da Lista 2. Basicamente, estou atualizando o local da conta 12345 com um HTTP PUT para esse endereço. A resposta será um documento JSON reconhecendo a solicitação.

O documento de localização

Para criar meu documento de localização, usarei o Morphia, uma biblioteca semelhante ao ORM para estabelecer a correspondência entre POJOs e o MongoDB. Meu documento de localização, representado por um POJO, é mostrado na Lista 3:

Lista 3. Criando o documento de localização
@Entity(value = "locations", noClassnameStored = true)
public class Location {
 @Id
 private ObjectId id;

 private String accountId;
 private double latitude;
 private double longitude;
 private Date timestamp;

 public Location(String accountId, Date timestamp, double lat, double lon) {
  this.accountId = accountId;
  this.timestamp = timestamp;
  this.latitude = lat;
  this.longitude = lon;
 }

 public void save() throws Exception {
  Mongo mongo = new Mongo("gnome.mongohq.com", 34256);
  Datastore datastore = new Morphia().createDatastore(mongo, "magnus", 
     "username", "password".toCharArray());
  datastore.save(this);
 }
}

Observe que eu codifiquei permanentemente as informações de conexão no MongoHQ — algo que você provavelmente nunca desejaria fazer na vida real. No entanto, funciona para fins de demonstração!

Eu amarro tudo isso com um controlador simples no Play e uma definição de rota. O controlador atuará como terminal para receber solicitações de JSON. Minha definição de rota é mostrada na Lista 4:

Lista 4. Uma definição de rota no Play
PUT /location/{id}     Application.saveLocation

Essa definição estabelece que todas as solicitações HTTP PUT para um URI que correspondem ao padrão /location/{some id} serão roteados para o método saveLocation da classe Application .

Finalmente, saveLocation é quase tão simples quanto o que você vê na Lista 5:

Lista 5. O método saveLocation
public static void saveLocation(String id, JsonObject body) throws Exception {
 double latitude = body.getAsJsonPrimitive("latitude").getAsDouble();
 double longitude = body.getAsJsonPrimitive("longitude").getAsDouble();
 String when = body.getAsJsonPrimitive("timestamp").getAsString();

 SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm");
 Date dt = formatter.parse(when);

 new Location(id, dt, latitude, longitude).save();
 renderText("success");
}

O Play passa o ID à direita para a URL solicitada (ou seja, 12345) e o corpo do JSON (eu tive que criar uma ligação JSON, documentada no Web site do Play). Eu obtenho prontamente alguns dados a partir do documento JSON — mais especificamente, latitude, longitude e hora — crio uma instância de Location e a salvo. Finalmente, forneço uma resposta — que, por enquanto, é somente uma sequência de texto — mais tarde eu alterarei essa resposta e implementarei uma nova versão. Não há manipulação de erros neste código, mas isso seria necessário em um aplicativo no "mundo real".

Uma rápida verificação de funcionamento

Meu aplicativo atualmente tem um terminal acessível que só aceita solicitações JSON, e a preparação disso requer algumas ferramentas. Também gostaria de ter um terminal normal que eu possa acessar com um navegador para me certificar de que tudo esteja funcionando após a implementação do aplicativo. Portanto, implementarei o método index na classe do Play chamada Application (que é chamada por padrão se você acessa o caminho-raiz) para retornar um texto rapidamente. Em outras palavras, incluirei renderText("Magnus Web is live");) no método index da classe Application .

Minha última etapa é criar um arquivo WAR para implementar no Beanstalk, que é basicamente um contêiner Tomcat. Com o Play, eu simplesmente executo o comandoplay war -o ../magnus --zip, que criará um arquivo chamado magnus.war que contém o meu aplicativo do Play.

Com isso, meu aplicativo de coleta de local — que não se preocupa com a privacidade e logo será um grande sucesso — está desenvolvido. Minha próxima etapa é garantir que ele tenha a grande escalabilidade do Beanstalk da qual irá precisar quando as pessoas perceberem que o fornecimento constante do local é uma boa ideia — certo?


O Magnus escala o Beanstalk

Supondo que você tenha feito a inscrição no Beanstalk, você começa fazendo login no AWS Management Console. A partir daí, selecione a guia Elastic Beanstalk e, em seguida, clique na opção Upload your own application , seguida pelo botão Launch Application . Ao fazer isso, aparecerá um diálogo que solicita algumas informações, como mostra a Figura 1:

Figura 1. Criando um novo aplicativo do Beanstalk
Criando um novo aplicativo do Beanstalk

Neste diálogo, é necessário fornecer um nome, que também será a URL do aplicativo. Também é necessário fornecer um arquivo WAR. Depois de clicar no botão Continue , você voltará ao AWS Management Console, enquanto o aplicativo é acionado. Isso pode demorar um pouco — por exemplo: eu já vi tempos de até dez minutos.

Depois que o aplicativo é totalmente implementado e tudo é configurado na extremidade da Amazon, você deve ver uma caixa verde ao lado do nome do aplicativo. A luz verde significa que o aplicativo está pronto para o uso, como se pode ver em Figura 2:

Figura 2. Magnus is ready!
Magnus is ready!

Quando eu clico na URL oferecida pela Amazon — magnus.elasticbeanstalk.com — vejo que o meu aplicativo está funcionando. Observe que o que você vê na Figura 3 é resultado do código que eu incluí na seção "health check":

Figura 3. Magnus lives!
Magnus lives!

Configurando o Beanstalk

Você começa a ver o verdadeiro poder do Beanstalk ao clicar no link Edit Configuration na seção Environmental Details, na parte inferior do Management Console do Beanstalk. Ao clicar nesse link, é exibido um diálogo com várias opções, inclusive algumas possibilidades muito interessantes.

Figura 4. Editando a configuração do ambiente
Editando a configuração do ambiente

O Beanstalk oferece várias opções de implementação de alto nível — incluindo a quantidade de memória, desempenho de E/S, armazenamento local, etc. — que você deseja para as instâncias do aplicativo. Também permite configurar o balanceador de carga do aplicativo e a escala automática do aplicativo, que é a opção que controla os nós horizontais. Com a escala automática, você decide quantas instâncias do aplicativo que devem ser executadas e como acionar cada nova instância.

A escala automática é um aspecto excepcionalmente potente do Beanstalk, que coloca a escalabilidade do aplicativo diretamente em suas mãos. Você poderia, por exemplo, configurar a escala automática para acionar novas instâncias com base em alguma métrica, como o tráfego recebido. Quando o tráfego diminui, a escala do aplicativo o acompanha — tudo isso sem nenhuma intervenção manual. Isso é computação elástica de verdade!


Faça o teste

Com o Magnus funcionando na Web, vamos testar a inclusão de locais a uma conta de amostra. Eu irei "trapacear" usando uma ferramenta para enviar por push um documento JSON ao meu terminal. O RESTClient usa HTTP PUT para enviar um documento JSON para o meu aplicativo. Como é possível ver na Figura 5, até agora as coisas estão indo bem:

Figura 5. o RESTClient relata o recebimento de uma carga útil
o RESTClient relata o recebimento de uma carga útil

A verificação de integridade final é ver se o documento JSON persistiu no MongoDB — que, como você deve lembrar, está executando no MongoHQ.

Figura 6. Interface do MongoHQ mostrando o documento de localização do Magnus
Interface do MongoHQ mostrando o documento de localização do Magnus

Eu deixei a resposta do terminal bastante simples na fase inicial do desenvolvimento de aplicativo. Agora eu quero fazer uma pequena mudança e reimplementar o aplicativo.


Implementações com versão

O Beanstalk, como o GAE, suporta implementações com versão. Sendo assim, é possível ter diversas versões implementadas, mas somente uma "ativa" em qualquer momento determinado. Esse recurso permite mover facilmente entre as versões conforme a necessidade; por exemplo: retroceder caso uma implementação dê errado.

Clique na guia Versions, no canto superior esquerdo da seção Application Details do console do Beanstalk para ver o seu primeiro release.

Figura 7. O Beanstalk exibe uma versão do aplicativo
O Beanstalk exibe uma versão do aplicativo

Na minha máquina local, mudarei o método saveLocation da classe Application . Especificamente, vou fazer com que a última linha do método seja renderJSON("{success}");. A resposta retornará um documento JSON simples em vez de uma sequência de texto simples.

Ao clicar no botão Upload New Version , você deve ver o diálogo já conhecido, mostrado na Figura 8. Aqui eu forneço para o arquivo WAR uma etiqueta de versão.

Figura 8. Reimplementando o Magnus
Reimplementando o Magnus

Como é possível ver na Figura 8, especifiquei que quero que o arquivo WAR seja transferido por upload, mas não implementado. Após a transferência do arquivo WAR por upload, eu posso implementá-lo como quiser por meio da guia Versions.

Figura 9. Reimplementando o Magnus e fazendo uma nova versão se tornar padrão
Reimplementando o Magnus e fazendo uma nova versão se tornar padrão

Eu cliquei na caixa de seleção ao lado da versão desejada. Agora eu posso fazer com que essa seja a versão em produção, simplesmente clicando no botão Deploy Version , como mostra a Figura 9.

Obviamente, se você quiser desativar o Beanstalk, poderá fazer isso. Você deve acessar a caixa suspensa Actions, no lado direito do console de gerenciamento, e selecionar Terminate the Environment. Não se esqueça de excluir também os arquivos WAR com versão. O valor do espaço no S3 será cobrado até que você faça isso!

Figura 10. Terminando o Beanstalk
Terminando o Beanstalk

Subindo e descendo no Beanstalk

O Elastic Beanstalk oferece aos desenvolvedores o acesso imediato à infraestrutura EC2 da Amazon e a torna muito mais configurável que o GAE. Como eu demonstrei com o meu aplicativo remoto baseado em local, até mesmo um framework da Web Java novo como o Play foi bem-vindo e a persistência de documentos por meio de instâncias do MongoDB executando em MongoHQ.com não foi problemática.

No caso do meu aplicativo, eu não precisei iniciar nenhum banco de dados, nenhuma instância do Tomcat, nem me certificar de que as portas estivessem abertas. O processo foi simples e rápido. Melhor ainda: meu aplicativo escalará automaticamente para quatro instâncias no caso de um pico de tráfego, com um balanceador de carga em frente que eu não precisei configurar. Por outro lado, seria possível ter mais controle se eu quisesse, como o meu pequeno experimento referente a implementações com versão mostrou. O custo inicial total foi imbatível: US$ 0,00.

O Beanstalk da Amazon é somente uma das várias alternativas de PaaS que estão surgindo para deixar o panorama do Java 2.0 mais rico e interessante. Conforme as empresas inteligentes e inovadoras começam a encontrar novos nichos nesse espaço em crescimento, podemos ter certeza de que o desenvolvimento rápido em ambientes corporativos, com custo mínimo, veio para ficar.

Recursos

Aprender

Obter produtos e tecnologias

  • Amazon Elastic Beanstalk: leia a documentação de referência, inscreva-se e comece a usar a alternativa de PaaS ao GAE, oferecida pela Amazon.
  • O framework Play: chamado de framework Java desenvolvido por desenvolvedores da Web, o Play tem como foco a produtividade dos desenvolvedores e é voltado para arquiteturas com REST.
  • MongoDB: um banco de dados voltado para documentos com uma enorme capacidade de escala. É escrito em C++ mas usa documentos no estilo JSON para armazenamento, que o tornam compatível com Java.
  • MongoHQ: armazenamento de banco de dados hospedado do MongoDB na nuvem.

Discutir

  • Participe da comunidade do developerWorks. Entre em contato com outros usuários do developerWorks, enquanto explora os blogs, fóruns, grupos e wikis orientados ao desenvolvedor.

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Tecnologia Java, Software livre, Cloud computing
ArticleID=632740
ArticleTitle=Desenvolvimento em Java 2.0: Escale o Elastic Beanstalk
publish-date=03162011