Escalabilidade na CLOUD da Amazon - Revista .net Magazine 100

O objetivo do artigo é mostrar ao leitor os principais recursos do Amazon Web Services para a criação de aplicações web preparadas para crescer usando os recursos de elasticidade e o benefício de pagar apenas pelo seu consumo.

Por que eu devo ler este artigo:

O objetivo do artigo é mostrar ao leitor os principais recursos do Amazon Web Services para a criação de aplicações web preparadas para crescer usando os recursos de elasticidade e o benefício de pagar apenas pelo seu consumo.

O tema é útil sempre que precisamos construir projetos, onde a preocupação está voltada para a disponibilidade, capacidade de atender demandas de acesso que podem variar constantemente. Um bom exemplo é um site de compra coletiva, que deve ter uma grande infraestrutura que não caia no momento que for lançado uma promoção esperada por uma grande massa, mas uma estrutura bastante enxuta no momento que não houver grandes ofertas no ar, evitando assim o desperdício de recurso.

Escalabilidade e Disponibilidade na CLOUD da Amazon

Escalabilidade, disponibilidade e performance são pontos fundamentais de preocupação no momento que a nossa aplicação vai para a produção. Será que o seu sistema está apto a escalar? Como seu sistema irá se comportar se receber 100 mil acessos simultâneos? A construção de uma aplicação pensando nesses pontos, aliados a uma boa estrutura de CLOUD, como o AWS, são fundamentais para seu êxito. Iremos apresentar um pouco da estrutura do AWS, como construir uma pequena aplicação pensando nesses pontos e como disponibilizar em uma estrutura escalável, pronta para atender a qualquer cenário.

É cada vez maior a necessidade de termos projetos de baixo custo e que possam estar preparados para um crescimento esperado ou não, afinal de contas, ninguém quer ver usuários insatisfeitos ou chateados por não conseguirem utilizar um determinado recurso do seu sistema, por lentidão ou por indisponibilidade devido a um pico de acesso. Nesse ponto é que a CLOUD se encaixa perfeitamente: baixo custo e alta performance quando necessário.

Com o advento da nuvem, empresas com pouco ou nenhum recurso tiveram a possibilidade de criar seu negócio online, por exemplo. Outro fator que contribuiu para isso é que os principais serviços de nuvem possuem período de gratuidade.

Para podermos desfrutar dessas vantagens proporcionadas pelo uso da CLOUD, precisamos pensar nos impactos causados quando utilizamos este tipo de ambiente antes de construir nossa aplicação e saber quais pontos precisam estar adaptados para a nuvem. Precisamos também saber como gerenciar o serviço na nuvem que utilizaremos. No nosso caso, usaremos o serviço chamado Elastic Beanstalk, do AWS, para realizar o deploy da nossa aplicação de exemplo e configurarmos ela para escalar de forma automática, baseado nos parâmetros que mais são críticos para o seu cenário. Em nosso exemplo usaremos como criticidade o processamento.

A CLOUD e seus principais recursos

Não é de hoje que o termo CLOUD vem sendo bastante debatido e explorado pelos desenvolvedores, principalmente aqueles que têm um enfoque na arquitetura. O conhecimento dos recursos fornecidos por cada uma das “nuvens” que temos no mercado pode ser determinante nas decisões que um arquiteto irá tomar na hora de desenhar a arquitetura para um projeto. Por isso, é fundamental conhecermos a grande diferença entre Data Center e CLOUD.

Quando você está usando a CLOUD, você terá acesso a recursos como Elasticidade e Disponibilidade. Com a Elasticidade você se depara com o recurso capaz de configurar o poder de processamento, memória e até mesmo a largura de banda que sua aplicação precisa para atender aos clientes que irão acessá-la. Outro ponto fundamental é que sua aplicação utilize esses recursos sem intervenção humana, pois ficaria inviável se fosse necessário estar 24 horas monitorando a aplicação para poder aumentar seu poder de processamento manualmente. Para os que gostam, podemos também configurar alarmes para que sejamos avisados no momento em que a nossa estrutura precisar de um upgrade. O fator Disponibilidade é outra característica fundamental, caracterizada por disponibilizar geograficamente nossa aplicação usando as mais diversas regiões do globo. Um exemplo disso seria uma aplicação em cluster rodando no Japão, São Paulo e América do Norte. Caso haja um furacão na América do Norte, e/ou um Tsunami no Japão, nossa aplicação ainda assim estaria disponível.

Atualmente temos uma grande oferta de serviços de CLOUD no mercado, mas as empresas que realmente se destacam com seus serviços de nuvem, são: a Microsoft com o Windows Azure, e a Amazon com o AWS. Estes oferecem período de gratuidade para testar seus serviços antes de pagar. O AWS tem a vantagem de oferecer bem mais que os três meses disponibilizados pelo Azure para teste, onde desfrutamos de 12 meses de gratuidade em uma série de serviços. Mas é claro que nem tudo é de graça. No momento que você realiza o cadastro é explicado isso e você irá pagar apenas seu excedente. Não é por acaso que precisamos informar um cartão de crédito válido para realizar o nosso cadastro. Mas fiquem tranquilos, vocês podem acompanhar diariamente o consumo.

AWS e os principais serviços

O AWS está entre as principais estruturas de nuvem existentes no mercado. A grande vantagem do AWS é a série de serviços que temos à disposição com poucos cliques. Após realizado o cadastro no site do AWS (disponível na seção Links) e autenticado no serviço, podemos entrar no AWS Management Console, que é a área de gerenciamento, onde temos acesso a todos os serviços, conforme Figura 1. Em History temos os últimos serviços acessados. Na coluna logo à direita temos a opção de acessar os serviços por área ou então ver todos, através da opção All Services. Nesse modo vemos os recursos de uma forma mais resumida, exibindo apenas uma imagem e o seu nome.

Figura 1. Serviços Disponíveis no AWS.

Caso você selecione algumas das áreas, que estão logo abaixo de All Services, você obterá os serviços para aquela área contendo uma descrição do mesmo, como podemos ver na Figura 2.

Há alguns que podemos dar um maior destaque, principalmente para o nosso cenário, que é falar de disponibilidade e escalabilidade. O primeiro deles é o Elastic Beanstalk, que detalharemos mais a frente. Outro serviço, que é comumente utilizado para quem está ingressando na CLOUD e possui um legado, onde será necessária uma máquina virtual para funcionar (semelhante ao que é entregue por um data center), é o EC2 (Elastic Compute Cloud). Através desse serviço instanciamos uma máquina virtual Windows Server 2008 com IIS e SQL Server 2008, em alguns minutos, por exemplo. Para quem vai precisar de serviço de banco temos o Amazon RDS (Relational Database Service), onde podemos facilmente levantar um novo servidor SQL Server, MySQL ou Oracle, com a mesma velocidade que criamos uma instância EC2 com Windows Server 2008.

Figura 2. Selecionando a área do serviço.

O Elastic Beanstalk

O Elastic Beanstalk é um serviço que realiza o deploy e o autogerenciamento de nossos sistemas de forma bastante simples. Ele conta com alguns recursos, como um balanceador de carga conhecido como Load Balancer, e o auto escalonamento ou Auto Scaling.

O balanceador ficará acima da sua aplicação, ou seja, entre a internet do usuário e as instâncias de sua aplicação. Na Figura 3 temos um cliente se conectando à nossa aplicação. Veja que ele é direcionado para o Load Balancer e que irá chamar a nossa aplicação, que está publicada em quatro instâncias, direcionando as requisições para o servidor com maior disponibilidade.

Já o Auto Scaling irá funcionar com base em alguns alarmes que você irá programar, onde será informado, por exemplo, que sua aplicação precisará instanciar uma nova máquina caso atinja um processamento superior a 75% por três vezes consecutivas num intervalo de 5 minutos.

Figura 3. Exemplo do Load Balancer.

O inverso também é configurável. Imagine o número de acessos simultâneos ao seu sistema às 4 da manhã. É pouco provável que sua aplicação precise de várias instâncias para atender o número de visitantes. É possível também configurar os requisitos que irão determinar que sua aplicação deva desalocar instâncias. Você pode, por exemplo, determinar que quando sua aplicação obtiver um processamento inferior a 30% por 5 vezes consecutivas num intervalo de 5 minutos deva ser desalocado uma ou mais instâncias.

Visando controlar seus custos e evitar que sua aplicação cresça de forma excessiva, você tem a capacidade de indicar, por exemplo, o número máximo de instâncias que sua aplicação pode alocar para atender a demanda.

Outro ponto de destaque para o Elastic Beanstalk é que ele possui uma política para verificar a saúde de suas instâncias. Caso ele verifique que uma determinada instância não está se comportando corretamente ou está inacessível, ele automaticamente remove-a do seu ambiente, aloca uma nova instância e faz o deploy de sua aplicação nela, deixando seu ambiente novamente saudável.

Publicando um projeto no Elastic Beanstalk

Para começarmos a trabalhar com o Elastic Beanstalk de forma prática vamos primeiramente criar um novo projeto, usando o ASP.NET MVC 4 e o .NET Framework 4.0 e criar um simples projeto de exemplo com um template vazio. Podemos chamar esse projeto de “ExemploAWS”.

O propósito do nosso projeto é apenas utilizar os recursos de sessão, que por padrão estão disponíveis no IIS. Devemos extrair essa sessão para uma área que não dependa da instância que estamos conectando, ou então usar os recursos da nossa CLOUD para contornar um redirecionamento indesejado, como impossibilitar recuperar as informações da sessão. Além disso, será mostrado como fazer o deploy no Elastic Beanstalk através de um Package gerado pelo Visual Studio 2012 (ou por outra versão).

Vamos incluir um novo Controller, chamado de UsuarioController que deverá ser composto de sua action criada por padrão (a Action Index), além de mais duas actions que serão chamadas de “RealizarAutenticacao” e “AcessoNegado”. A primeira será responsável apenas por verificar se o nome existente na sessão de nome usuario é igual à “devmedia”; caso seja, será retornada a indicação que o usuário está autenticado com sucesso, caso contrário, será retornado o resultado da action “AcessoNegado”. A action RealizarAutenticacao será responsável por armazenar na sessão de nome usuário a string “devmedia", caso ela não seja igual a esse valor. Se isso acontecer, será apenas indicado que o usuário já está autenticado. Como todas as actions retornam string, não precisaremos criar Views. O resultado da implementação desse controller deverá estar semelhante à Listagem 1. Para concluir, modifique a rota default, apontando o controller para “UsuarioController”.

Para a geração do pacote, no Visual Studio 2012 esta opção está agrupada na opção “Publish”. Depois de selecionada, basta criar um novo profile e informar na aba “Connection” que o método de publicação é “Web Deploy Package” e informar o local de destino para mandar publicar, como podemos ver na Figura 4.

Listagem 1. Código Título.
using System.Web.Mvc; namespace ExemploAWS.Controllers { public class UsuarioController : Controller { public string Index() { if (Session["usuario"] == "devmedia") return "Você está autenticado com sucesso"; else return AcessoNegado(); } public string RealizarAutenticacao() { if (Session["usuario"] == "devmedia") return "Usuario já está autenticado"; Session["usuario"] = "devmedia"; return "Usuario autenticado com sucesso"; } public string AcessoNegado() { return "Você não tem acesso"; } } }
Figura 4. Gerando um package do projeto de exemplo.

Na Figura 5 podemos ver a área disponível no AWS Management para realizar o deploy de uma nova aplicação. Veja que informamos simplesmente o nome do ambiente, URL, descrição, o pacote do projeto que queremos publicar, que para o nosso caso será o zip que geramos no Visual Studio. Para o nosso caso temos um Windows Server 2008 rodando o IIS 7.5.

Figura 5. Área para realizar o deploy de sua aplicação usando o Elastic Beanstalk.

Depois de preenchidos os campos e mandarmos avançar, nos deparamos com uma nova janela para informarmos o tipo de instância que queremos para realizar o deploy de nossa aplicação. A indicação do tipo de instância é fundamental para definirmos uma série de recursos, como a quantidade de memória, poder de processamento, desempenho de I/O e armazenamento.

Uma informação importante é que as instâncias criadas pelo Elastic Beanstalk são instâncias EC2, ou seja, para sabermos o que significar uma instância “t1.micro”, podemos utilizar a tabela de tipos de instâncias EC2 que está disponível na seção Links. Todas elas estão bem explicativas e em português. Veja na Figura 6 a descrição apresentada pela Amazon para uma instância “t1.micro”.

Figura 6. Informações sobre a instância t1.micro.

Perceba que na última linha, em “Nome da API”, temos o nome que encontramos para selecionar no deploy de nossa aplicação.

Selecionado a instância, podemos opcionalmente preencher os campos “Existing Key Pair” e “Email Address”. A primeira opção será útil quando se fizer necessário o acesso remoto à instância criada. Já o campo “Email Address” será útil para que o nosso serviço nos notifique sobre acontecimentos importantes em nossa aplicação, como o deploy de uma nova aplicação ou quando uma instância não estiver mais saudável. É bastante importante, pois através dela iremos informar uma URL, que será monitorada periodicamente, para indicar a saúde de sua instância.

O ideal é criarmos uma página simples, chamada “Eco”, sem nenhuma operação, apenas retornando uma simples mensagem. O carregamento com sucesso dessa página indicará que a instância está saudável. Por padrão, esse caminho será a raiz da nossa aplicação. Na janela seguinte, temos um review das nossas configurações para confirmarmos que está tudo certo para criar o nosso ambiente como podem ver na Figura 7.

Figura 7. Janela indicando resumo dos dados selecionados antes de criar o ambiente.

Agora precisamos aguardar a criação da instância, contendo o Windows Server 2008 R2 com IIS 7.5, e o deploy de nossa aplicação na mesma. Todo esse processo leva apenas alguns minutos. Esse tempo é exatamente o referente à criação da nossa instância, configuração do Load Balancer e deploy de nossa aplicação nesse ambiente.

Após isso, já podemos acessar o nosso ambiente pelo endereço que indicamos. A partir desse momento, o Elastic Beanstalk já está monitorando e gerenciando nossa aplicação. Na parte superior, pode acessar “Services > EC2” e na sequência selecionamos “Instances”. Na página que é exibida podemos ver a instância alocada, com alguns indicativos importantes, como o type indicando que é uma instância t1.micro, e o State informando que a instância está rodando normalmente, como mostrado na Figura 8.

Como temos um cenário extremamente simples, essa máquina irá atender perfeitamente à nossa necessidade. Agora, imagine que nosso sistema tenha uma criticidade em processamento. Se recebermos um número grande de acessos, certamente teríamos problemas com essa máquina. Para contornar esse tipo de situação com um custo extremamente flexível e sem desperdício, precisamos aprender a configurar o Auto Scaling para que ele possa ter um comportamento adequado ao nosso projeto.

Figura 8. Ambiente EC2 com instância criada pelo Elastic Beanstalk.

Configurando o Auto Scaling do Elastic Beanstalk

Um dos grandes recursos do Elastic Beanstalk é o Auto Scaling. Através dele podemos escalar a capacidade da nossa aplicação horizontalmente, sem precisar nos preocupar com o direcionamento das requisições, quando nossa aplicação escalar.

Com uma série de configurações disponíveis, podemos definir a métrica que mais se enquadre para a nossa realidade e fazer com que o número de instâncias que atendam a nossa aplicação aumente ou diminua em proporções também determinadas.

Para configurarmos o Auto Scaling da nossa aplicação, precisamos estar no ambiente do Elastic Beanstalk no AWS Management Console e depois clicar na opção “Actions”, que está disponível do lado direito das informações do nosso ambiente. Escolha a opção “Edit/Load Configuration”, conforme mostrado na Figura 9.

Figura 9. Ambiente Elastic Beanstalk após aplicação ter sido criada.

Na janela que carregar você irá encontrar inúmeros recursos disponíveis para configuração do seu ambiente. Para a nossa configuração devemos ir para a aba Auto Scaling, conforme mostrado na Figura 10. Temos à disposição várias opções que nos permitem escalar de forma automática a nossa aplicação. As primeiras opções dizem respeito ao número mínimo e máximo de instâncias que queremos em nosso ambiente. Como o valor inicial para o número máximo de instâncias é de 1, nossa aplicação não irá escalar. Esses números também podem ter motivação financeira no momento da escolha, pois se você delimitar o número máximo de instâncias para 6, por exemplo, já pode imaginar o máximo que irá pagar caso sua aplicação sempre demande esse número de instâncias.

Na opção seguinte podemos selecionar as zonas de disponibilidades de nossas instâncias. Depois de escolhidas, o AWS fará a distribuição geográfica de suas instâncias à medida que elas forem sendo requeridas.

Também podemos configurar o tempo entre as tomadas de decisões pelo Auto Scaling, através do “Scaling Cooldown Time”. Esse tempo é medido em segundos e indica o delay para incremento ou decremento do número de instâncias.

Figura 10. Primeira etapa da aba para configuração do Auto Scaling.

No tópico Scaling Trigger iremos configurar os critérios adotados para a tomada de decisões, como podemos ver na Figura 11. Na primeira opção informaremos qual a métrica a ser utilizada. Para o nosso cenário informaremos “CPUUtilization” a título de exemplo, mas temos diversos indicadores, como tráfego de rede, latência, contagem de requisições e escrita em disco. É fundamental que você conheça a arquitetura e características de sua aplicação para determinar qual desses indicadores é o mais adequado para a mesma. Na sequência informaremos qual a estatística a ser coletada. Como estamos falando de utilização de CPU então vamos coletar a média, ou seja, Average. Isso irá variar também com a métrica escolhida. Caso a métrica escolhida tenha sido latência, por exemplo, a unidade de medida mais adequada seria “seconds”, determinando o tempo de latência em segundos. Seguindo em diante precisamos dizer a unidade de média, que obviamente vamos informar “Percent”. As próximas opções são “Measurement Period” e “Breach Duration”. O primeiro servirá para indicar o período de coleta das informações para a tomada de decisão, enquanto o segundo vai ser o tempo de violação para executar o escalonamento. Podemos informar 2(minutos) para o primeiro e 1(minuto) para o segundo. Nesse caso se a cada 2 minutos o tempo de violação exceder 1 minuto haverá um escalonamento. Os próximos parâmetros indicarão:

Figura 11. Segunda etapa da aba para configuração do Auto Scaling.

Continuando na janela de configurações, na primeira aba temos opções para a configuração do servidor, onde podemos determinar quais são os tipos de instâncias EC2 que irão compor nosso ambiente. Temos também recursos para definição de grupo de segurança, onde podemos, por exemplo, determinar políticas de acesso entre máquinas. Outra opção é definir o intervalo de monitoramento do nosso ambiente.

Configuração do Servidor e Load Balancer para o Elastic Beanstalk

Dando sequência, temos a aba Load Balancer, como podemos ver na Figura 12. Inicialmente temos as configurações que determinam em qual porta o Elastic Beanstalk ficará escutando para direcionar as requisições (por padrão ele fica na porta 80). Além disso, temos as configurações referentes à saúde da nossa aplicação, onde podemos modificar a URL que determinamos no momento da criação do nosso ambiente, como também determinar o intervalo de tempo que aquela URL deve ser checada. Ainda nessa aba, também podemos configurar o timeout para essa URL. Se ela não responder nesse intervalo de tempo por um número específico de vezes aquela instância não será considerada saudável e automaticamente o Load Balancer não irá mais direcionar requisições para ela. Esse número de vezes consecutivas que o nosso ambiente não obtiver sucesso em sua resposta é configurado na opção seguinte, em “Unhealthy Check Count Threshold”. A opção anterior a essa (Healthy Check Count Threshold) irá indicar o número de vezes que a aplicação deverá responder com sucesso antes de ser considerada saudável. Esse último é geralmente usado quando uma nova instância é alocada. Após a máquina ter sido instanciada e o deploy da aplicação ter sido realizado é iniciado esses testes e o Load Balancer só irá direcionar as requisições para essa instância caso ela passe nesse teste.

Figura 12. Configuração do Load Balancer.

Para finalizar a aba do Load Balancer temos outro recurso muito importante que é a área de Sessions. Nessa área temos duas configurações ao nosso alcance, que são “Enable Session Stickiness” e “Cookie Expiration Period(seconds). A compreensão delas é fundamental quando estamos preocupados com escalabilidade. Ao marcar a primeira opção estamos dizendo ao Load Balancer que quando um determinado cliente começar a realizar requisições em uma instância, todas as suas requisições serão sempre direcionadas para ela.

Notifications e Container

As demais abas da área de configuração possuem recursos complementares aos que já mostramos. Na aba “Notifications” temos simplesmente a opção de informar o email que irá receber as notificações sobre eventos importantes na sua aplicação, como o deploy de novas versões e quando sua aplicação escalar.

Para finalizar temos a aba “Container”, onde podemos definir configurações para o IIS, de forma que se aplique a todas as instâncias, como definir a versão do Framework a ser utilizada, habilitar nosso container para rodar em modo 32 bits e direcionar os logs de cada instância para uma área centralizada, chamada de S3, que é um dos serviços do AWS para armazenamento de documentos.

Finalizando essa aba, temos a opção “Environment Properties”. Através dessa opção podemos compartilhar parâmetros para a nossa aplicação entre todas as instâncias. Podemos ver essas opções através da Figura 13.

Figura 13. Configuração do Load Balancer.

Problemas ao Escalar

Conhecendo o recurso apresentado (Enable Session Stickiness), podemos colocar ele em prática através do nosso projeto de exemplo, que publicamos. O critério para diferenciar um cliente do outro, em uma aplicação, é a sua sessão. Só utilizando essa opção você irá evitar uma série de comportamentos indesejados. Vamos agora simular um comportamento indesejado com esse projeto. Para isso precisaremos apenas montar um ambiente igual ao da Figura 3.

Para levantarmos outras instâncias podemos ir à aba Auto Scaling e informar que o número mínimo de instâncias é de quatro. Depois de aplicado as configurações e aguardarmos alguns minutos, podemos acessar o ambiente do EC2 e ver que já temos o número mínimo, que fora informado, de instâncias atendendo à nossa aplicação, como podemos ver na Figura 14.

Figura 14. Ambiente EC2 com 4 instâncias atendendo ao nosso projeto.

Se acessarmos a action “RealizarAutenticacao” e em seguida a action “Index” veremos o retorno da mensagem indicando que o nosso usuário está autenticado com sucesso. Caso você realize várias requisições à action “Index” você verá que em determinados momentos será retornado a mensagem indicando que o usuário não está autenticado, como podemos ver na Figura 15. Como sabemos a sessão é um recurso que está disponível no IIS. Caso o Load Balancer tenha direcionado o nosso usuário para a instância 1 no momento da autenticação, essas informações estarão disponíveis somente nesta instância. Se não realizarmos nenhuma configuração, caso o Load Balancer direcione alguma requisição do nosso usuário para outra instância, que necessite de autenticação, como a instância 2, por exemplo, receberemos essa mensagem informando que o usuário não está autenticado já que nessa instância não temos nenhuma informação de autenticação desse usuário. Agora marque a opção “Enable Session Stickiness” e aplique. Realize o mesmo fluxo de acesso às actions e veja que o problema de direcionamento das requisições está resolvido, como vemos na Figura 16. Com essa simples mudança podemos agora ter uma aplicação que poderá escalar sem termos comportamentos indesejado, como o acesso indevido à informação de uma sessão que não exista.

Figura 15. Aplicação de exemplo, após autenticado, sem usar o recurso “Enable Session Stickiness”.
Figura 16. Aplicação de exemplo, após autenticado, usando o recurso “Enable Session Stickiness”.

Conclusão

Como pudemos ver o conhecimento da CLOUD foi decisivo para a configuração do nosso projeto e permitir que ele possa Auto Escalar, de forma horizontal, nos permitindo um controle excelente sobre os custos, evitando desperdiçar recurso.

É interessante também que você busque alternativas e veja como elas se comportam na CLOUD, como o armazenamento de sessão em banco. Além disso, devemos ter a curiosidade de explorar os demais recursos do Elastic Beanstalk, testar novos cenários, derrubar suas instâncias EC2 e ver seu ambiente se recuperar automaticamente.

Não se limite a esse serviço. A exploração dos demais serviços irão trazer um leque de possibilidades que irão agregar produtividade ao desenvolvimento e performance à nossa aplicação.

Links

Artigos relacionados