Dev (Back & Front)ARTIGO

Aplicativos egocêntricos e escaláveis

A ascensão do cloud computing ao longo dos últimos anos tem sido incrível. Infelizmente, muitos ainda não veem o interesse ou não compreendem a sua importância.

Este artigo não é sobre cloud computing e seus benefícios, mas sim uma atualização sobre a compreensão de algumas regras básicas de escalabilidade e como começar a construção de aplicativos escaláveis, mantendo em mente que a maioria das pessoas e das empresas possui orçamentos limitados.

O conceito de arquiteturas shared-nothing é bem conhecido na comunidade de escalabilidade – se tal coisa existe mesmo -, mas parece ser frequentemente esquecido quando se trata de construção aplicativos web.

Escalabilidade

Antes de nos aprofundarmos na teoria de escalabilidade, vale lembrar que aplicativos rápidos e infraestruturas não necessariamente escalonam.

Embora a escalabilidade seja um conceito complexo e difícil de explicar, o sentido geralmente aceito para definir escalabilidade é a capacidade de um sistema lidar com uma quantidade crescente de trabalho de uma maneira competente. Em outras palavras, é a capacidade de lidar com mais carregamentos, adicionando mais poder de computação. Você é capaz de lidar com mais usuários se adicionar mais servidores ao seu cluster?

Escalabilidade é sobre a capacidade de ajustar e adaptar. Como Darwin disse uma vez (ou quis dizer):

Não é o aplicativo web mais rápido que sobrevive a picos e popularidade; é o que é mais adaptável à mudança.

Share nothing

Durante anos, o mundo PHP (a maior parte dele) foi implementado em um único servidor que continha o servidor web, os bancos de dados, os arquivos enviados, os arquivos de sessão etc.

Essa configuração ultrapassada se parece com isto:

 

Isso foi bom até sites começarem a cair por causa de uma menção no Digg ou Slashdot (para aqueles que se lembram do Slashdot). Os apps eram rápidos, mas não podiam ultrapassar um certo limite de usuários.

Trata-se de quando o conceito de arquiteturas shared-nothing começou a pegar. As infraestruturas agora estão dissociadas, e cada componente pode ser facilmente substituído. Essa configuração melhorada se parece com isto:

 

Ao usar shared nothing, cada servidor que alimenta o seu aplicativo se torna egocêntrico e não se importa com o resto da infraestrutura. Como um código modular orientado a objetos, partes da sua infraestrutura se tornam independentes. Por exemplo, o servidor web não deve mais salvar sessões em arquivos locais, porque, em algum dado momento, o número de servidores web pode mudar.

Um sistema que está intimamente ligado ao seu sistema de arquivos para upload de arquivos, bancos de dados, sessões etc., não é escalável. Felizmente, no mundo PHP, temos algumas ferramentas para nos ajudar a atingir um alto grau de egoísmo.

Sessões

Armazenar sessões em um único sistema de arquivos significa que, quando o sistema escala e adiciona ou remove servidores, algumas sessões serão perdidas. Existem algumas soluções para esse problema.

Memcached

Memcached vem sendo utilizado por muitos anos no mundo PHP e é uma ótima maneira de armazenar objetos e sessões em um cluster de servidores. Para uma infraestrutura Memcached ainda mais escalável, eu recomendo Membase, que é de código aberto e proporciona elasticidade, bem como a persistência de Memcached.

Após configurar sua infraestrutura do memcached (e a extensão PHP), você simplesmente modifica o seu ponteiro de sessão para apontar para o servidor memcached (ou pool) como o exemplo a seguir:

<?php
ini_set('session.save_handler', 'memcached');
ini_set('session.save_path', '1.2.3.4:11211');

Muitas pessoas não gostam de usar memcached para armazenamento de sessão porque os dados são efêmeros e, por isso, se o servidor morre, todas as suas sessões irão desaparecer e seus usuários serão desconectados.

Membase evita esse problema e é totalmente compatível com o protocolo Memcached.

Redis

Uma alternativa para a distribuição de sessões persistentemente em clusters de computadores é usar Redis e a extensão Redis PHP.

Redis é um armazenamento avançado de chave-valor (servidor de estrutura de dados) que pode conter strings, hashes, listas, conjuntos e conjuntos classificados. Redis pode ser replicado e, apesar de ser um sistema de memória, também pode ser usado para armazenar dados em disco.

Depois de instalar a extensão PHP mencionada, você modifica o apontador de sessão para utilizar Redis:

<?php
ini_set('session.save_handler', 'redis');
ini_set('session.save_path', '1.2.3.4:6379');

Você pode especificar vários servidores no evento onde desejar usar um cluster de instâncias Redis:

<?php
ini_set('session.save_handler', 'redis');
ini_set('session.save_path', 'tcp://1.2.3.4:6379?weight=1, tcp://4.3.2.1:6379?weight=2');

SessionHandler

O PHP 5,4 possui uma nova classe chamada SessionHandler. Ela permite que você escreva um um objetivo orientado a session handler personalizado. Se você salvar suas sessões para Memcached usando SessionHandler,  ficaria mais ou menos assim:

<?php
class MemSession extends SessionHandler {

public function read($key) {
return parent::read(sha1($key));
}

public function write($key, $value) {
return parent::write(sha1($key), $value);
}
}

ini_set('session.save_handler', 'memcached');
ini_set('session.save_path', '1.2.3.4:11211');
session_set_save_handler(new MemSession);

Claro, as sessões podem ser, e frequentemente são, salvas em um banco de dados. Usar SessionHandler é agora mais fácil do que nunca!

Armazenamento redundante e distribuído de arquivos

Uma outra limitação da maioria dos aplicativos da web tradicionais é salvar os arquivos para um sistema de arquivos local.

Se um app escala adicionando mais servidores, salvar os arquivos para o sistema de arquivos tem as mesmas limitações de salvar as sessões para o sistema de arquivos. A presença de arquivos será inconsistente entre os nós e seus usuários ficarão frustrados.

Uma solução para esse problema é usar sistemas que são construídos para armazenar, distribuir e reproduzir arquivos em várias regiões. Um bom exemplo é o Amazon S3, que pode ser facilmente suportado com Zend_Service_Amazon_S3 ou PEAR :: Services_Amazon_S3.

Para Symfony2, eu uso um pacote que criei chamado symfony2-s3streambundle. Ele permite que você grave logs e arquivos similares de forma fácil diretamente no Amazon S3 usando Monolog.

Uma vez que o pacote está instalado, e seu bucket do Amazon S3 é criado, tudo que você precisa fazer é modificar o arquivo app/config/config_prod.yml para acrescentar o seguinte:

monolog:
handlers:
nested:
type:  stream
path:  s3://your-bucket/%kernel.environment%.log
level: debug

Existem outras formas de distribuir arquivos, como construir seu próprio cluster de sistema de arquivos usando GlusterFS, NFS, ou qualquer outra variante de um sistema de armazenamento de arquivos distribuído e, eventualmente, consistente. Eu geralmente recomendo usar o Amazon S3, porque é rápido, confiável, altamente disponível e possui um suporte amplo.

Conclusão

Com o cloud computing se tornando mais padronizada, e plataformas como Orchestra fornecendo arquiteturas escaláveis com o clique de um mouse, a arquitetura de aplicativos está se tornando mais importante, enquanto a arquitetura de infraestrutura mais simples e confiável.

Existem mais coisas a se ponderar ao construir uma arquitetura verdadeiramente escalável, como fila de mensagens, replicação de banco de dados, backups automáticos, solução automática de problemas, elasticidade e localidade. O PHP possui muitas extensões e ferramentas para ajudar seu aplicativo a escalar.

Em uma nota relacionada, se você não possui conhecimento dos projetos Gearman e ZeroMQ, eu recomendo aprender mais sobre eles e considerar se eles poderiam se encaixar em seu projeto atual ou no próximo.

***

Texto original disponível em http://phpadvent.org/2011/egomaniacal-and-scalable-apps-by-david-coallier

 

Matérias especiais e reportagens conduzidas internamente pela Redação iMasters. Acompanhe no Twitter @imasters e no Instagram/Threads @portalimasters

Ver perfil