Quando se trabalha numa empresa como a boo-box, é preciso ter uma equipe capaz de desenvolver soluções tecnológicas extraordinárias, em um espaço de tempo extraordinário.
Nos últimos meses, a boo-box experimentou um crescimento sensacional:

Como podem ver, o aumento de exibição de publicidade deu um salto de 85% no último mês!
Para aguentarmos o ritmo, os sistemas tiveram que ser revistos e reestruturados.
Antes de uma explicação mais detalhada, vou resumir nossa abordagem: monitore ao máximo, use cache em tudo o que puder, e cuide bem do seu banco de dados :)
Explicando em detalhes
Para se destacar como um player de publicidade online
, é preciso seguir alguns princípios:
- Velocidade: ninguém vai ficar esperando para ver um anúncio carregar.
- Escalabilidade: viralizações, crescimentos acelerados etc. Se sua aplicação não for altamente escalável, melhor mudar de atividade, ou abrir mão de dormir todos os dias :)
- Monitoramentos: monitore tudo! E automatize os monitoramentos sempre que possível.
- Processos: crie, e siga, processos para os diversos tipos de situações.
Com isso em mente, nossos Ninjas fizeram um refactoring no coração do sistema: na
Camada de Aplicação.
O objetivo era esgotar ao máximo a capacidade das linguagens e plataformas nginx + Ruby + Merb + MySQL, com algoritmos e topologias mais poderosos.
Portanto, mudamos a lógica, sincronicidade e cacheamento de partes-chave. Em comparação com o post anterior “A infraestrutura de servidores Web do Sistema boo-box“, alguns pontos da topologia foram alterados:

Além disso, implementamos metodologias de monitoramento que nos fizeram ter maior controle sobre a aplicação.
Nomes das máquinas e versões de releases
Conforme explicamos no post anterior sobre nossa infraestrutura, nossas máquinas são batizadas em homenagem a personagens do anime Dragon Ball Z
, como Korin, Kami, Cell, Raditz, Trunks, Goku, Gohan entre outros.
Ultimamente, começamos também a identificar nossos releases, que levam nomes de filmes clássicos. Os dois primeiros releases foram:
- Metropolis, do clássico de ficção científica de 1927 de Fritz Lang;
- Hannibal, filme de 2001 bastante conhecido.
Cluster Application
Essa camada é composta pelo conjunto de servidores que processam nossas regras de negócio. São eles que decidem quais anúncios serão exibidos nas vitrines, o que acontece quando há um clique e o que fazer com os dados de um novo publisher cadastrado no sistema.
Essa foi a camada com maiores modificações. O refactoring priorizou quatro pontos essenciais:
- Lógica: otimizamos o algoritmo de processamento, tornando-o muito mais eficiente para esta nova fase do sistema.
- Memcached: aumentamos em 80% a utilização de memcached. Sempre respeitando as regras de negócio, foi possível cachear grande quantidade de informações de forma a otimizar o tempo de resposta. Essa alteração afetou diretamente a camada de banco de dados de aplicação, pois fez com que a aplicação consultasse consideravalmente menos esse banco de dados.
- Gravação de logs: tornamos a gravação de logs assíncrona. Isso quer dizer que a camada de aplicação não fala mais diretamente com nosso MySQL
de logs. Ele coloca numa fila (Beanstalkd) que, posteriormente, será consumida por um programa Ruby que, por sua vez, será responsável por armazenar no banco de dados.
- Número de Workers: fizemos alguns benchmarks que nos indicaram o número ideal de workers. Antes, usávamos uma lógica complexa que media a capacidade total de processamento de cada máquina para chegar no número ideal que era, à época, muito alto. Porém, nossos benchmarks indicaram que esse número não deve ser muito grande. Quanto mais workers, mais os núcleos (cores) das máquinas ficarão ocupados e, portanto, mais lento será o processamento individual deles. Porém, se esse número for pequeno demais, o loadbalancer poderá não achar workers disponíveis, mesmo que eles processem rapidamente. No nosso caso, o número ideal está entre 20 e 30 workers.
Testamos também a utilização do método run_later do MERB. Porém, chegamos à conclusão que teríamos maior poder de gerenciamento usando o Beanstalkd. Além disso, o Beanstalkd possui uma funcionalidade de persistência.
Cluster Log e BI
Todas as requisições feitas a boo-box são gravadas em nosso Cluster de Log. Vitrines visualizadas, cliques em anúncios, ações efetuadas em sites de parceiros, tudo é registrado.
Como disse no começo do post: tome cuidado com seu banco de dados
! Ele poderá tirar suas noites de sono :)
Nessa camada, foi importante unir tunning com processamento assíncrono:
- Tunning: fique atento às configurações de key_buffer, max_connections, table_cache, thread_concurrency, innodb_buffer_pool_size e, claro, à sua estrutura de índices nas tabelas.
Além disso, implementamos um sistema de particionamento nativo do MySQL que otimiza a estrutura de armazenamento no HD (MySQL Reference Manual – Chapter 18. Partitioning).
- Processamento assíncrono: como explicado no Cluster Application, a aplicação não fala mais diretamente com os banco de dados de logs, mas sim com uma fila. Dessa forma, um não dependerá mais do outro, melhorando, e muito, o tempo de resposta de nossas vitrines.
Essas otimizações também afetaram nosso BI, responsável por processar todos os dados recebidos para serem utilizados posteriormente (relatórios, métricas, projeções etc).
Cluster data source
Essa camada é responsável por armazenar informações específicas do sistema.
Com todas as otimizações feitas nas outras camadas (principalmente o aumento de utilização de Memcached), não foi necessário realizar grandes modificações aqui. Pelo contrário: reduzimos a quantidade de máquinas dessa camada, diminuindo o número de servidores.
Cluster products cache
Grande parte dos anúncios exibidos nas vitrines boo-box são produtos ofertados por e-commmerces parceiros. Como as informações dos produtos não precisam ser mantidas ao longo do tempo, fazemos um cache temporário dos dados.
Com as alterações no Cluster Application, foi possível diminuir consideravelmente a quantidade de máquinas dessa camada.
Lembre-se: sempre que utilizar CouchDB ou MySQL, é importante ter máquinas de armazenamento rápido, para uma melhor performance de I/O. Portanto, Cloud Computing pode não ser uma boa opção para essa camada.
Load balancer e Static Files
São as máquinas que recebem as requisições dos usuários e direcionam a carga para um dos servidores de aplicação.
No webserver nginx, usávamos o algoritmo round-robin. Com o aumento de escala, essa lógica se mostrou não ser a melhor pra nós, pois quando algum de nossos servidores (workers) demorava a responder, comprometia todas as requisições que ali entravam. Dessa forma, aplicamos o módulo Fair, que permite ao nginx enviar requisições para as máquinas de aplicação que estiverem com menor processamento no momento.
Monitor
Para garantir a saúde dos sistemas, é importante monitorar ao máximo as diversas camadas e aplicativos envolvidos. Porém, isso não requer apenas ferramentas. É importante implantar processos manuais e automáticos.
Atualmente, utilizamos ferramentas como Munin, Monit, Webalizer, Pingdom além de ferramentas próprias que fazem esse papel.
Realizamos checks horários, diários, semanais e mensais, que nos geram dados para tomadas de decisão de mudanças ou manutenção da nossa estrutura.
É importante observar que a automatização de processos é a meta ideal, porém não deve ser impeditivo. Muitos técnicos e gestores de infraestrutura negligenciam as práticas de monitoramento por “não terem automatizado o processo”, gerando muito mais problemas do que soluções. Se necessário, implemente processos manuais constantes. A disciplina é sua maior aliada.
Conclusão
Construir um sistema de alta disponibilidade não requer apenas soluções tecnológicas.
Práticas de gestão serão um diferencial necessário na solução final. Sem se perder no excesso de burocracia, a criação de processos e práticas de trabalho bem definidas farão com que a equipe possa unir soluções de longo prazo (implementação lenta), com soluções de curto prazo (implementação veloz), sabendo, portanto, lidar com todos os tipos de problemas que um sistema dessa complexidade irá criar.
Quem faz isso acontecer
