77
UNIVERSIDADE FEDERAL DE SANTA CATARINA SISTEMAS DE INFORMAÇÃO RUBY ON RAILS ESCALÁVEL: ESTUDO E SOLUÇÕES GABRIEL GONÇALVES NUNES MAZETTO TRABALHO DE CONCLUSÃO DO CURSO Orientador: Prof. Leandro José Komosinski Florianópolis, 2011

Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

Embed Size (px)

Citation preview

Page 1: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

UNIVERSIDADE FEDERAL DE SANTA CATARINA

SISTEMAS DE INFORMAÇÃO

RUBY ON RAILS ESCALÁVEL:ESTUDO E SOLUÇÕES

GABRIEL GONÇALVES NUNES MAZETTO

TRABALHO DE CONCLUSÃO DO CURSO

Orientador:Prof. Leandro José Komosinski

Florianópolis, 2011

Page 2: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

GABRIEL GONÇALVES NUNES MAZETTO

RUBY ON RAILS ESCALÁVEL:ESTUDO E SOLUÇÕES

Trabalho de conclusão de curso apresentado como parte das atividades para obtenção do grau de Bacharel em Sistemas de Informação pela Universidade Federal de Santa Catarina a Gabriel Gonçalves Nunes Mazetto.

Orientador: Prof. Leandro José Komosinsk

Banca Examinadora:

Renato Fileto

Mario Dantas

Florianópolis, 2011

Page 3: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

Dedico este trabalho a todas as

pessoas que de alguma forma contribuíram

com a realização deste, em especial aos

amigos da área de tecnologia que

participaram de inúmeras discussões e trocas

de informação sobre o tema, a minha

namorada, pela paciência e compreensão e a

minha família pela educação e oportunidade

que me deram.

Page 4: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

AGRADECIMENTOS

Agradecimentos aos amigo Nassor

Paulino da Silva, por toda ajuda e troca de

conhecimentos que foram fundamentais a

conclusão deste trabalho, Guilherme Arthur

Gerônimo, pela oportunidade de trabalhar

durante meu estágio com diversas questões

relacionadas ao assunto deste TCC, ao meu

orientador, pelas várias horas de atendimento

durante a elaboração deste trabalho, e as

diversas pessoas dentro da SeTIC/UFSC que

foram fundamentais para tornar este trabalho

realidade.

Page 5: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

“640kB devem ser bastantes para qualquer um.”

Bill Gates, 1981

Page 6: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

RESUMO

Este trabalho contém um estudo sobre as técnicas de escalabilidade aplicado ao contexto de aplicações Web, focado no framework de desenvolvimento Ruby on Rails.

É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) que podem ser utilizados com o framework, juntamente com um mapeamento dos problemas de escalabilidade que podem afetar uma aplicação web em geral, e quais desses problemas se manifestam em uma aplicação construída utilizando Ruby on Rails.

Este trabalhado traz além de simulações para avaliar soluções de escalabilidade horizon-tal e vertical, uma proposta para construção de aplicações Multi-Site, tratando a questão de es -calabilidade de aplicações como serviço (SaaS).

Palavras-chave: Ruby on Rails, escalabilidade, Ruby, web, SGBD, NoSQL, Benchmark.

Page 7: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

ABSTRACT

This document contains a study of scalability techniques applied to the context of Web Applications, with focus to the web development framework, Ruby on Rails.

It contains a list of many different sorts of web servers, relational databases, non-relation-al databases, that can be used with the framework, also contains a list of the chief scalability problems that can affect a web application, and which of this can affect one built using Ruby on Rails.

This document brings, in addition to simulations to help analyze scalability solutions, a proposal on how to build Multi-Site web applications, dealing with Software as a Service scalability problem.

Keywords: Ruby on Rails, scalability, Ruby, web, DBMS, NoSQL, Benchmark.

Page 8: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

LISTA DE ILUSTRAÇÕES

Gráfico 1: Benchmark entre principais servidores web para Ruby..........................................27

Gráfico 2: Tempo de execução do benchmark realizado pelo "Programming Zen".................36

Gráfico 3: Consumo de memória do benchmark realizado pelo "Programming Zen".............40

Gráfico 4: Valor médio de requisições por segundo do Apache e Nginx pela carga de conexões

concorrentes.............................................................................................................................. 61

Gráfico 5: Tempo médio de resposta das requisições pelo Nginx em baixa concorrência.......62

Gráfico 6: Tempo médio de resposta das requisições pelo Apache em baixa concorrência.....63

Gráfico 7: Tempo médio de resposta das requisições pelo Nginx em alta concorrência..........64

Gráfico 8: Tempo médio de resposta das requisições pelo Apache em alta concorrência........65

Gráfico 9: Valor médio de requisições por segundo do Apache+Passenger e Nginx+Passenger

pela carga de conexões concorrentes........................................................................................ 66

Gráfico 10: Comparativo de performance entre o resultado do Teste 1 e Teste 2....................68

Gráfico 11: Benchmark simulando escalabilidade vertical.......................................................70

Gráfico 12: Benchmark para 1 e 2 nodos em ambiente com distribuição de cargas................72

Page 9: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

SUMÁRIO

Lista de ilustrações..................................................................................................... 6

Introdução.................................................................................................................. 10

1.1 Motivação................................................................................................................... 11

1.2 Metodologia................................................................................................................ 11

2 Escalabilidade.........................................................................................................13

2.1 Definição.................................................................................................................... 13

2.2 Tipos de escalabilidade.............................................................................................. 13

2.2.1 Verticalmente Escalável (scale up).................................................................................... 14

2.2.2 Horizontalmente Escalável (scale out)...............................................................................14

2.3 Maneiras de medir escalabilidade.............................................................................. 14

2.3.1 Escalabilidade de Carga.................................................................................................... 14

2.3.2 Escalabilidade Geográfica................................................................................................. 14

2.3.3 Escalabilidade administrativa............................................................................................ 14

2.3.4 Lei de Amdahl.................................................................................................................... 15

2.4 Soluções comuns para problemas de escalabilidade................................................. 15

2.4.1 Balanceamento de Carga.................................................................................................. 16

2.4.2 Balanceamento de Armazenamento.................................................................................. 16

2.4.3 Balanceamento de Rede................................................................................................... 17

2.4.4 Balanceamento de CPU.................................................................................................... 18

3 Escalabilidade em aplicações para web.............................................................. 19

3.1 Introdução.................................................................................................................. 19

3.2 Arquitetura Web.......................................................................................................... 19

3.3 Problemas de escalabilidade...................................................................................... 20

3.3.1 Aplicações com processamento intenso............................................................................ 20

3.3.2 Aplicações com enormes necessidades de armazenamentos..........................................21

3.3.3 Aplicações que precisem atender um grande número de usuários...................................22

3.3.4 Aplicações Multi-Site..........................................................................................................22

3.4 Conclusão.................................................................................................................. 24

Page 10: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

8

4 Escalabilidade em Ruby on Rails.........................................................................25

4.1 Introdução.................................................................................................................. 25

4.2 Servidores Web para Ruby........................................................................................ 25

4.2.1 Webrick............................................................................................................................. 26

4.2.2 Mongrel............................................................................................................................. 26

4.2.3 Thin................................................................................................................................... 27

4.2.4 Possibilidades Futuras...................................................................................................... 27

4.3 Servidores Web de múltiplo propósito........................................................................ 28

4.3.1 Apache2.2......................................................................................................................... 28

4.3.2 Nginx................................................................................................................................. 30

4.3.3 Lighttpd............................................................................................................................. 30

4.3.4 Cherokee........................................................................................................................... 31

4.4 Servidores de Banco de Dados Relacional................................................................ 31

4.4.1 SQL Lite............................................................................................................................ 31

4.4.2 MySQL.............................................................................................................................. 32

4.4.3 PostgreSQL....................................................................................................................... 32

4.5 Servidores de Banco de Dados NoSQL..................................................................... 33

4.5.1 Introdução......................................................................................................................... 33

4.5.2 MongoDB.......................................................................................................................... 33

4.5.3 CouchDB........................................................................................................................... 34

4.5.4 Cassandra......................................................................................................................... 34

4.5.5 Hadoop database.............................................................................................................. 34

4.5.6 Redis................................................................................................................................. 34

4.6 Implementações da linguagem Ruby......................................................................... 35

4.6.1 Comparativos de performance.......................................................................................... 37

4.7 Problemas.................................................................................................................. 41

4.7.1 Número crescente de acessos.......................................................................................... 41

4.7.2 Necessidade crescente de processamento de informações............................................. 42

4.7.3 Aplicações com necessidade crescente de armazenamento de dados ou arquivos.........42

4.7.4 Aplicações Multi-Site......................................................................................................... 43

4.8 Soluções.................................................................................................................... 43

4.8.1 Arquitetura escalável para aplicações com muitos acessos..............................................43

4.8.2 Aplicações que necessitem processar muitas informações..............................................46

4.8.3 Aplicações com necessidade de armazenar muitos dados/arquivos................................47

4.8.4 Aplicações Multi-Site......................................................................................................... 48

4.9 Como identificar gargalos (bottlenecks)..................................................................... 52

4.9.1 Monitoramento e Análise de performance......................................................................... 52

Page 11: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

9

5 SIMULAÇÕES......................................................................................................... 54

5.1 Configuração..............................................................................................................54

5.1.1 Ambiente de Virtualização................................................................................................. 56

5.1.2 Instalação do Passenger + Ruby 1.9.2............................................................................. 57

5.1.3 Máquina Virtual Apache2 + Passenger............................................................................. 58

5.1.4 Máquina Virtual Nginx + Passenger.................................................................................. 58

5.2 Metodologia............................................................................................................... 58

5.3 Ferramentas...............................................................................................................59

5.3.1 Apache Benchmark........................................................................................................... 60

5.3.2 Gnuplot.............................................................................................................................. 60

5.4 Cenários.................................................................................................................... 60

5.4.1 Comparativo entre soluções de servidor multi-propósito...................................................60

5.4.2 Comparativo de escalabilidade horizontal vs. vertical com Ruby on Rails........................ 69

6 Conclusão...............................................................................................................73

Page 12: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

INTRODUÇÃO

Este trabalho tem por finalidade apresentar uma série de estratégias e soluções, para pro-

blemas de escalabilidade, relacionados a aplicações Web desenvolvidas utilizando o fra-

mework Ruby on Rails, em sua ultima versão, atualmente 3.0.

Por questões ideológicas do autor, o foco deste trabalho será em soluções que se adequem

ao conceito de software livre ou free software1 pela Free Software Fundation. Pelas mesmas

razões, não farão parte do universo de pesquisa sistemas operacionais, aplicações e compo-

nentes considerados proprietários ou “não livres”. No entanto, a existência deles poderá ser

comentada.

O sistema operacional de referência para esse trabalho é o Ubuntu Linux, de forma que

todos os exemplo, configurações, aplicativos e trechos de código foram testados e executados

nele. O fato da escolha não limita este trabalho e suas soluções a esta distribuição em específi-

co, sendo que qualquer outra distribuição que atinja os requisitos mínimos dos softwares e

versões compatíveis, serão capazes de reproduzir resultados semelhantes, atentando as especi-

ficidades de cada uma.

Ainda o fato da escolha do sistema operacional, não inviabiliza por completo que algu-

mas soluções possam funcionar de forma completa ou parcial também em outros sistemas que

sejam capazes de rodar o framework Ruby On Rails, porém a essas, o autor deixa o leitor a ta-

refa de experimentar e adaptar.

1 A definição conceitual e filosófica pode ser encontrada no endereço: http://www.gnu.org/philosophy/free-sw.html [EN]

Page 13: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

11

1.1 Motivação

Existem diversos tipos de tecnologias para desenvolvimento de aplicações web, algumas

se baseiam em linguagens e trabalhos acadêmicos, outras, estritamente nas necessidades do

mercado.

Ruby on Rails é um caso de tecnologia que surgiu atendendo estritamente necessidades

do mercado. Sua concepção se deu a partir da extração de parte do código-fonte da ferramen-

ta Basecamp da 37 signals, na época em fase ainda embrionária, teve sua primeira release em

julho de 2004, com licença de código livre.

De lá pra cá, conquistou espaço mundialmente na industria de desenvolvimento de

software, concentrando o conhecimento a seu respeito e a direção do seus desenvolvimento

no ecossistema criado em torno da mesma, composta por desenvolvedores entusiastas e algu-

mas empresas.

Devido suas características e sua origem essencialmente no mercado, muito pouco co-

nhecimento acadêmico foi gerado a respeito desta tecnologia. Além deste fato, com a adoção

crescente da mesma, para projetos de médio e grande porte, criou-se um vazio de conheci-

mento separando as empresas e desenvolvedores que passaram pela necessidade de escalar

suas aplicações e adquiriram o conhecimento de como fazê-las, daquelas que ainda não o fi-

zeram.

Com isso, fica claro a necessidade colaborar com a geração de conhecimento acadêmico

a respeito do assunto, procurando oferecer informações e ferramentas para aqueles que dese-

jam desenvolver aplicações que possam escalabilidade utilizando o framework Ruby on

Rails.

1.2 Metodologia

Para entender o problema é necessário primeiramente compreender os conceitos funda-

mentais de escalabilidade e o que influencia uma aplicação a ser ou não escalável.

Page 14: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

12

Portanto, será apresentado no capítulo 2 o embasamento teórico relacionado a escalabili-

dade, seus tipos, e os problemas mais comuns que sistemas de maneira em geral apresentam,

relacionados a ela.

No capítulo 3, o foco passará para aplicações Web, e portanto será visto de que forma o

problema de escalabilidade se apresenta neste contexto e quais as soluções que geralmente

são feitas. Essas informações ampliam a utilidade deste trabalho, tornando parte dele utilizá-

vel para outras tecnologias que não a foco deste.

No capítulo 4 o problema de escalabilidade será abordado no contexto específico de apli-

cações Ruby on Rails, listando os casos comuns, soluções, e um levamtamento dos diversos

componentes de infra-estrutura que poderão ser utilizados ao desenvolver uma aplicação, em

conjunto com seus pontos positivos e negativos.

No capítulo 5, serão feitas a execução de algumas simulações em conjunto com medi-

ções, para auxiliar a avaliação das estraégias de escalabilidade, que poderão ser repetidas em

conjunto com uma aplicação real, para avaliar a melhor estratégia a ser adotada.

Pretende-se fornecer informações que sejam úteis a auxiliar na implementação de código

para tornar as aplicações escaláveis, em conjunto com a sugestão de algumas ferramentas,

plugins, servidores, etc disponíveis atualmente.

Page 15: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

2 ESCALABILIDADE

2.1 Definição

“Em telecomunicações e na engenharia de software, escalabilidade é uma caracterís-tica desejável em todo o sistema, em uma rede ou em um processo, que indica sua habilidade de manipular uma porção crescente de trabalho de forma uniforme, ou es-tar preparado para crescer”. (André B. Bondi, 2000. p. 195- 203)

De maneira mais geral, pode-se afirmar que um sistema é escalável quando o mesmo tem

a capacidade de crescer, seja em numero de utilizadores, em quantidade de requisições, em

quantidade de dados armazenados, processados etc, sem necessidade de reescrita ou alteração

considerável no código.

Um sistema capaz de escalar (escalável) é um sistema que continua eficaz quando há um

aumento significativo do número de recursos e utilizadores, em que não é necessário alterar a

implementação dos componentes e da forma de interação das mesmas. Num sistema escalá-

vel, as seguintes propriedades devem ser verdadeiras:

• Os recursos envolvidos devem aumentar linearmente com a dimensão do sistema

• O aumento na dimensão dos dados/recursos não deve levar a uma diminuição sig-

nificativa do desempenho – a redução não deve ser superior a O(log n).

2.2 Tipos de escalabilidade

A escalabilidade pode ser analisada por diversos ângulos.

Page 16: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

14

2.2.1 Verticalmente Escalável (scale up)

Significa adicionar recursos em um único nó do sistema (mais memória ou um disco rígi-

do mais rápido).

2.2.2 Horizontalmente Escalável (scale out)

Significa adicionar mais nós ao sistema, tais como adicionar um novo computador com

uma aplicação para clusterizar o software.

2.3 Maneiras de medir escalabilidade

Existem algumas maneiras de medir ou determinar que um sistema é escalável.

2.3.1 Escalabilidade de Carga

Quando um sistema distribuído deve ser fácil para ser expandido e usar sua gama de re-

cursos para acomodar tanto exigências do mesmo sendo elas pouca ou excessiva.

2.3.2 Escalabilidade Geográfica

Um sistema é geograficamente escalável quando ele mantém sua performance, utilidade

e usabilidade, independente da maneira como ele está distribuído, isto é, ele consegue ir de

uma arquitetura mais concentrada para uma mais distribuída.

2.3.3 Escalabilidade administrativa

Não importa a variação de informação que diferentes organizações necessitam comparti-

lhar em um único sistema distribuído, ele deve permanecer fácil de ser usado e gerenciado.

2.3.3.1 Escalabilidade Funcional

Um sistema é funcionalmente escalável quando é possível adicionar recursos ou melhori-

as ao sistema com esforços mínimos.

Page 17: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

15

2.3.4 Lei de Amdahl

A Lei de Amdahl é a lei que governa o speedup (ganho) na utilização de processadores

paralelos em relação ao uso de apenas um processador. Seu nome deriva do arquiteto de com-

putadores Gene Amdahl.

O ganho de desempenho que pode ser obtido melhorando uma determinada parte do sis-

tema é limitado pela fração de tempo que essa parte é utilizada pelo sistema durante a sua

operação.

O ganho depende de dois fatores:

1. Fração de melhoria (Fm): fração de tempo da computação que pode tirar proveito

da melhoria feita. Esta fração é sempre menor ou igual a 1.

2. Ganho de execução (Ge): ganho obtido com a melhoria na parte específica modi-

ficada do sistema. Este ganho é sempre maior que 1.

ganho= 1

1−Fm Fm

Ge

Speedup pode ser definido como a relação entre o tempo gasto para executar uma tarefa

com um único processador e o tempo gasto com N processadores, ou seja, Speedup é a Medi-

da do ganho em tempo.

S=T 1T N

Onde S é o speedup e T(N) é o tempo gasto para N processadores Wikipédia (2010a)

2.4 Soluções comuns para problemas de escalabilidade

Podemos dividir os tipos mais comuns de soluções para problemas de escalabilidade em:

balanceamento de carga, balanceamento de armazenamento, balanceamento de rede e balan-

ceamento de CPU. Wikipédia (2010b)

Page 18: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

16

2.4.1 Balanceamento de Carga

Um serviço conforme comece a crescer, pode esbarrar nos limites do hardware ao qual

ele está atrelado, independente do quão caro e moderno seja. Nesse caso, é o momento em

que o serviço precisa ser distribuído por várias máquinas.

Os casos mais genéricos de problemas com limitação de hardware são relacionados a

processamento, memória ram, espaço de armazenamento limitações de rede. Wikipédia

(2010c)

2.4.2 Balanceamento de Armazenamento

O balanceamento do suporte de armazenamento permite distribuir o acesso a sistemas de

arquivos por vários discos (software/hardware RAID2), garantindo ganhos em tempos de

acesso. Estas soluções podem ser dedicadas ou existir em cada um dos servidores do cluster.

A distribuição dos dados quando objetivada para melhorar o tempo de acesso, tem como

desafios principais questões como replicação dos dados, garantia de integridade (garantir que

ao alterar o arquivo em uma copia principal, as cópias adicionais receberão também aquela al -

teração), transação (um arquivo precisa ser alterado, mas o mesmo está sendo acessado por

outros usuários, como garantir que seja feita a alteração e ao mesmo tempo que todos usuári-

os consigam ter o acesso ao conteúdo do arquivo naquele momento sem receber uma versão

corrompida?).

Quando esse tipo de replicação é feita utilizando-se de uma solução RAID, a complexi-

dade de implementação é reduzida, já que tudo acontece na máquina do servidor ou no stor-

age. Nesses casos, o próprio software ou hardware é quem cuida de todas as questões que en-

volvam a replicação e a garantia de integridade.

No caso da utilização de soluções com RAID, pode-se ganhar também em confiabilidade,

podendo ter redundância de disco em caso de falha.

Existe a possibilidade de se trabalhar com replicação através de algum serviço no sistema

operacional, replicando esses dados para outras máquinas da rede, utilizando por exemplo

2 Conjunto Redundante de Discos Independentes (Redundant Array of Independent Drives)

Page 19: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

17

rsync do Linux. Um exemplo de utilização dessa abordagem é a criação de mirrors (espelha-

mento de dados) de um repositório Linux, ou de um serviço de downloads.

Quando a necessidade de balancear o armazenamento se dá para conseguir ampliar sua

capacidade, os problemas passam a ser diferentes do primeiro caso.

Novamente a solução pode ser feita diretamente na própria máquina, através da adição de

mais hardwares de discos, utilizar uma solução dedicada de storage, ou uma solução codifica-

da na própria aplicação que seja capaz de distribuir e recuperar esses arquivos em diversos

servidores diferentes.

No primeiro caso, dependendo das características do sistema operacional, no qual o ser-

viço está sendo disponibilizado, pode ser necessário que a aplicação seja adaptada, juntamen-

te com configurações específicas, para realizar o mapeamento desses discos.

2.4.3 Balanceamento de Rede

O balanceamento da utilização da rede resume-se em reencaminhar o tráfego destinado a

um destino específico que esteja sendo muito requisitado, para outros destinos alternativos

que também ofereçam o mesmo serviço/aplicação, a fim distribuir os acessos aos servidores.

Este balanceamento pode ocorrer a qualquer nível da camada OSI Wikipédia (2010c).

Um dos tipos mais comuns de solução para balanceamento em rede, na camada de aplica-

ção, é realizado utilizando o serviço de DNS3, responsável por prover a resolução de nomes

dos servidores. Através da utilização de um escalonador usando algorítimo de Round-robin,

distribui uniformemente entre os clientes, endereços distintos de máquinas.

Esta solução não é ideal, já que não baseia essa distribuição em nenhuma informação dos

servidores e nem garante que a carga de fato será distribuída uniformemente, pois os clientes

podem ter comportamentos diferentes uns dos outros.

Enquanto a solução utilizando DNS é uma das mais simples, a mesma não é considerada

confiável, já que pode repassar o tráfego para um servidor que não esteja disponível naquele

momento por algum motivo qualquer.

3 Do inglês Domain Name Server, refere-se a um dos serviços básicos de resolução de nomes da internet.

Page 20: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

18

Um balanceamento um pouco mais elaborado, pode ser feito, por exemplo, por uma apli-

cação servidora que receba a requisição e através de algum algoritmo próprio, repasse a mes-

ma para uma outra máquina em um cluster, agindo como se fosse um proxy. Este caso é co-

mumente utilizado quando o cluster de servidores provê algum serviço que seja muito acessa-

do ou que execute um processamento mais pesado.

Para implementar isso, utiliza-se uma aplicação servidora altamente paralelizável e de

baixa latência, para receber as requisições iniciais, fazendo a ponte entre as diversas outras

máquinas e os clientes.

Nessa solução é possível também que a aplicação servidora colete dados de carga e per-

formance das demais máquinas para conseguir distribuir de fato as cargas uniformemente,

bem como, realizar verificações para, caso algum dos servidores caia, não repasse o tráfego

para ele.

O problema da segunda solução é que ela se torna também um ponto de falha, não sendo

assim considerada 100% confiável se utilizada sozinha.

Uma alternativa para contornar esses problemas está na utilização de hardware específi-

co, conhecido como load balancer, que pode trabalhar na camada de rede ou até mesmo na

camada de aplicação. Este procura sanar tanto a questão de roteamento do tráfego, quando a

questão de garantir que o tráfego esteja sendo repassado para algum servidor que seja capaz

de responder. Dependendo do harware ou solução escolhida, pode utilizar outras variáveis

para levar em conta para qual máquina ele deve direcionar tais quais carga atual, uptime, etc.

2.4.4 Balanceamento de CPU

Este tipo de balanceamento é efetuado pelos sistemas de processamento distribuído e

consiste, basicamente, em dividir a carga total de processamento pelos vários processadores

no sistema (sejam eles locais ou remotos) Wikipédia (2010c).

Page 21: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

3 ESCALABILIDADE EM APLICAÇÕES PARA WEB

“Aplicação Web é o termo utilizado para designar, de forma geral, sistemas de in-formática projetados para utilização através de um navegador, na internet ou em re-des privadas ( Intranet ). Trata-se de um conjunto de programas que é executado em um servidor de HTTP (Web Host). O desenvolvimento da tecnologia web está rela-cionado, entre outros fatores, a necessidade de simplificar a atualização e manuten-ção mantendo o código-fonte em um mesmo local, de onde ele é acessado pelos di-ferentes usuários.

Pode-se definir uma aplicação web como uma aplicação de software que utiliza a web, através de um browser como ambiente de execução.” Wikipédia (2010d)

3.1 Introdução

Neste capítulo será abordado de maneira comparativa e com alguns exemplos teóricos,

quais as questões de escalabilidade que estão envolvidas em aplicações para Web e como as

soluções mais tradicionais procuram sanar esse problema.

3.2 Arquitetura Web

Não é objetivo deste trabalho detalhar o funcionamento da Web, mas de maneira simplifi-

cada podemos entender a arquitetura como composta por dois atores principais, um sendo o

cliente (geralmente acessando por um programa chamado navegador), e outro, servidor (po-

dendo este não necessariamente ser uma única máquina, se considerarmos sistemas distribuí-

dos).

Toda comunicação é feita através de protocolo HTTP4 que por sua vez é implementado

utilizando TCP e IP. Este protocolo é responsável pela requisição de recursos remotos (textos,

imagens, etc), envio de informações de formulários, etc. Wikipédia (2010e)

4 Hipertext Transfer Protocol – Protocolo de comunicação responsável pelo acesso a páginas web

Page 22: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

20

Uma aplicação Web, dependendo de como foi projetada e programada, pode rodar em um

simples servidor Web, ou rodar no chamado “servidor de aplicação”.

Segundo a Wikipédia (2010f) podemos definir um servidor Web como sendo: “um pro-

grama de computador responsável por aceitar pedidos HTTP de clientes, geralmente os nave-

gadores, e servi-los com respostas HTTP, incluindo opcionalmente dados, que geralmente são

páginas web, tais como documentos HTML com objetos embutidos (imagens, etc.)”.

Já sobre um servidor de aplicação, é definido como: “um servidor de aplicação ou em

inglês, application server, é um software que disponibiliza um ambiente para a instalação e

execução de certas aplicações. Os servidores de aplicação também são conhecidos como

software de middleware.

O objetivo do servidor de aplicações é disponibilizar uma plataforma que abstraia do de-

senvolvedor de software algumas das complexidades de um sistema computacional. No de-

senvolvimento de aplicações comerciais, por exemplo, o foco dos desenvolvedores deve ser a

resolução de problemas relacionados ao negócio da empresa, e não de questões de infraestru-

tura da aplicação. O servidor de aplicações responde a algumas questões comuns à todas as

aplicações, como segurança, garantia de disponibilidade, balanceamento de carga e tratamen-

to de exceções.” Wikipédia (2010g)

3.3 Problemas de escalabilidade

No contexto de aplicações Web, os problemas fundamentais de escalabilidade se mani-

festam de diversas maneiras diferentes e atingem principalmente, aplicações, conforme classi-

ficaremos a seguir.

3.3.1 Aplicações com processamento intenso

Considerando o cenário de uma aplicação Web que realize diversas tarefas que exijam

processamento mais intenso, existem dois caminhos tradicionais a serem seguidos:

Escalar verticalmente adicionando mais recursos de hardware a máquina servidora, para

suprir as necessidades computacionais crescentes, até atingir o limite que a arquitetura de

Page 23: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

21

harware permitir. Essa primeira abordagem é considerada mais limitada e pode resolver o

problema até determinado ponto.

Escalar horizontalmente, adicionando mais máquinas servidoras e distribuindo a carga de

acesso e processamento entre essas diversas máquinas. Essa abordagem é mais interessante

pois permite um crescimento muito maior do que a primeira.

Qualquer que seja o problema, não é necessário escolher apenas um caminho, podendo

combinar ambos procurando atingir melhores resultados.

3.3.2 Aplicações com enormes necessidades de armazenamentos

Algumas aplicações podem necessitar armazenar grandes volumes de dados, sejam eles

dados relacionais, que comumente são armazenados em bancos de dados realacionais, ou ar-

quivos de mídia tais como fotos, vídeos, planilhas, etc.

Quando falamos em dados relacionais, levamos o problema para o domínio dos bancos

de dados e neste caso, podem existir inúmeras maneiras de se tratar este problema.

Alguns bancos de dados são capazes de lidar com esse tipo de problema sozinhos e de

maneira transparente para a aplicação. Um banco de dados pouco conhecido do grande públi-

co, mas bastante explorado pela comunidade de desenvolvedores de Ruby on Rails é o Mon-

goDB5. Ele difere dos bancos de dados relacionais e se auto-classifica na categoria de “banco

de dados orientado a documento”. 10gen (2010)

Quanto ao volume de dados, novamente pode ser escalado de maneira vertical, utilizando

unidades de armazenamento realmente grandes, ou de maneira horizontal, dividindo o arma-

zenamento dessas informações em vários “nodos” (servidores).

Ao se utilizar a primeira opção o impacto mais claro é a performance das consultas, que,

por estarem trabalhando com enormes volumes de dados de maneira concentrada, tendem a

serem mais lentas. Por esse motivo, não é mais comum sua utilização.

5 Disponível em: http://www.mongodb.org/

Page 24: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

22

Ao trabalhar com a segunda alternativa, essa carga de processamento é dividida entre os

“nodos” da mesma forma que a responsabilidade pelo armazenamento. Essa distribuição rece-

be o nome de “Sharding” e no caso do MongoDB é feita de maneira transparente para a apli-

cação.

Algumas das técnicas implementadas por esse banco de dados, podem ser simuladas pela

própria aplicação Web e gerenciada por algum algorítimo, especificamente criado para isso,

quando o próprio banco de dados não der suporte a elas.

Quando analisamos o caso de aplicações que precisem trabalhar com um grande volume

de dados de mídia, os quais não estão armazenados em um banco de dados, podemos aplicar a

técnica de “Sharding” ou investir em unidades de armazenamentos grandes o suficiente.

3.3.3 Aplicações que precisem atender um grande número de usuários

Quando uma aplicação possui um grande número de usuários (e consequentemente de

acessos), e principalmente, se é um número crescente conforme o tempo, ela precisa ter sido

pensada desde o princípio para isso.

Neste cenário, podemos incluir as questões de armazenamento citadas anteriormente bem

como de processamento. Além dessas questões temos que levar em conta que parte da respon-

sabilidade está no servidor Web que deve ser capaz de atender as necessidades intensas de

acesso. A outra parte está na própria aplicação que deve ter seu código otimizado, sem garga-

los de performance e preparado para funcionar com um ambiente distribuído.

Nestes casos, a solução mais comum está em dividir os acessos em diversas máquinas,

quantas forem necessárias a demanda dos clientes. Essa abordagem pode trazer diversos desa-

fios, dependendo do suporte disponível pela arquitetura utilizada.

3.3.4 Aplicações Multi-Site

Existe um tipo específico de aplicação Web, que é feitos pensando em oferecer um servi-

ço para um grande número de pessoas, que se assemelha, em questão de funcionalidade e cus-

Page 25: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

23

tomização a noção de que “cada um possui uma própria instalação da aplicação”, mesmo não

sendo esse o caso.

Um exemplo clássico desse tipo de aplicação é o caso de blogs. Qualquer pessoa pode

instalar uma aplicação para disponibilizar um blog online, ou utilizar um serviço que cria e

hospeda seu próprio blog.

Na primeira situação em que existe de fato uma instalação para cada pessoa, se pensar-

mos em um serviço que trabalhe dessa maneira, conseguimos concluir rapidamente que existe

um certo desperdício de espaço em disco e replicação de código.

Pensando em aplicações Rails, o problema é ainda maior, já que isso implica também em

desperdício de memória RAM (já que cada aplicação deve ser iniciada por completo para res-

ponder as requisições, e após responder, continua ativa).

Existe também o problema de gerenciamento dessas diversas instalações, e o deploy de

novas versões. Contudo, a abordagem tradicional fornece algum nível de escalabilidade hori-

zontal “out of the box”, já que a “carga” acaba podendo ser dividida entre várias máquinas (e

as várias instalações da aplicação).

Como esse tipo de serviço, existe uma grande quantidade de outros serviços que se se en-

caixam nesse mesmo modelo. Dessa forma, é necessário pensar em uma estratégia para elimi-

nar esse disperdício e ao mesmo tempo oferecer uma escalabilidade maior e melhor que a so-

lução tradicional.

A maneira com que o maior serviço de blogs, o Wordpress.com encontrou, foi utilizar

uma mesma instalação física, para atender um número maior de endereços/proprietários de

blog, a qual está preparada para essa finalidade.

A solução utilizada por eles, pode ser estudada e aplicada para qualquer tipo de aplicação

Web, tornando elas também “Multi-site”. Esse modelo de construção de aplicação web, será

abordado em capítulo futuro, contextualizados para o framework Ruby on Rails.

Page 26: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

24

3.4 Conclusão

Pelo fato de aplicações Web serem diferentes de conteúdos estáticos HTML, existem uma

série de dificuldades que precisam ser tratadas quando pretende-se tornar o sistema escalável.

Alguns desses problemas precisam ser resolvidos no domínio de banco de dados, outros em

nível de hardware e parque de máquinas, mas acaba se tornando necessário na maioria dos ca -

sos que a aplicação seja pensada inicialmente para enfrentar esse tipo de situação, seja por ela

mesma, ou por algum framework que implemente as técnicas necessárias.

Page 27: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

4 ESCALABILIDADE EM RUBY ON RAILS

4.1 Introdução

Neste capítulo será abordado as questões de escalabilidade que envolvem o framework

Ruby on Rails, as soluções já existentes e problemas ainda em aberto.

Pode-se inicialmente considerar que os problemas que afetam de uma forma geral aplica-

ções Web também impactam nas aplicações que são feitas utilizando o framework Ruby on

Rails.

Dessa forma, devemos começar a análise pela camada de interação mais baixa de uma

aplicação Rails, que é composta pelo servidor Web. Em seguida passaremos pelos servidores

de bancos de dados e sua integração ao framework, as diversas implementações da linguagem

Ruby para então analisar os problemas e propor soluções.

Atualmente existem diversas opções de servidores que podem ser utilizados para rodar

aplicações Ruby on Rails. Neste trabalho estão sendo citados os principais, mais conhecidos e

relevantes ao problema que está sendo abordado.

4.2 Servidores Web para Ruby

Uma primeira categoria de servidores que podem ser mencionados são aqueles que foram

escritos especificamente para rodarem aplicações em Ruby.

Estes podem ser considerados servidores “especialistas” no sentido que eles foram desen-

volvidos para rodar códigos Ruby (consequentemente Ruby on Rails) e não se esforçam em

fazer muito mais que isso.

Page 28: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

26

Em ambiente de produção, dificilmente algum deles será utilizado sozinho, geralmente

em conjunto com um servidor web de propósito multiplo que será comentado a seguir.

4.2.1 Webrick

Talvez o servidor mais conhecido para aplicações Ruby on Rails, já que vem disponível

em todas aplicações construídas com o framework, por padrão. Ele geralmente é utilizado nas

fases iniciais de desenvolvimento.

Criado por Masayoshi Takahashi e Yuuzou Gotou juntamente com contribuições de ou-

tros desenvolvedores, ele é totalmente escrito em Ruby e funciona como um servidor HTTP

simplificado. Pela sua característica de ser uma implementação simplista, sem recursos para

atender grandes demandas, não é indicado para ambientes de produção. Wikipédia (2011a)

4.2.2 Mongrel

É uma biblioteca HTTP de código aberto e um servidor web para aplicações escritas em

Ruby, criado por Zed Shaw. Considerado o primeiro servidor web em Ruby que possui recur-

sos de escalabilidade.

O servidor em sí não é utilizado sozinho em ambiente de produção, por sua arquitetura

single thread não suportar uma carga grande de acessos. Configurações mais comuns são fei-

tas com várias instâncias do Mongrel em conjunto com Apache ou Nginx, estes fazendo papel

de balanceadores de carga.

Nessa arquitetura, o Apache ou Nginx, se encarregam de disponibilizar o conteúdo estáti-

co, e através de algum módulo de balanceamento de carga, distribui as requisições dinâmicas

entre os processos do Mongrel, de certa forma, contornando os efeitos da limitação de thread

única.

Além desses servidores mais comuns, outras soluções também são utilizadas como o

Lighthttpd ou ainda um hardware específico para balanceamento de carga entre as requisições

das instâncias do Mongrel. Wikipédia (2011b)

Page 29: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

27

4.2.3 Thin

O mais rápido dos três, desenvolvido utilizando o componente de parser do Mongrel, a

biblioteca EventMachine, uma biblioteca para lidar com operações de I/O da rede, que pro-

porciona alta performance, estabilidade e alta escalabilidade, e a biblioteca Rack, responsável

pela interface entre o servidor e a aplicação.

O Gráfico 1 a seguir demonstra testes feito6 com os principais servidores web para Ruby

e a relação de ganho de performance que o Thin consegue em relação aos demais:

4.2.4 Possibilidades Futuras

No dia 11 de junho de 2010 teve início o desenvolvimento de uma nova e versão do

Mongrel (chamada Mongrel2), que promete aproveitar a biblioteca de parser HTTP da versão

anterior, já bastante consolidada, porém com o restante da aplicação totalmente reescrito, ten-

do escalabilidade como objetivo principal.

Além do código ter sido repensado, houve mudanças estruturais que tornaram a aplicação

algo totalmente diferente da primeira versão.

Algumas das novas características são, segundo o próprio autor: “Mongrel2 is an appli-

cation, language, and network architecture agnostic web server that focuses on web applica-

tions using modern browser technologies.” SHAW (2011)

6 Disponível em: http://code.macournoyer.com/thin/

Gráfico 1: Benchmark entre principais servido-

res web para Ruby

Page 30: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

28

Quando ele fala sobre ser agnóstico a linguagem, quer dizer que não existe uma preferên-

cia pela linguagem que será utilizada, ou seja, não existe nenhum direcionamento a uma lin-

guagem de programação específica Wikipédia (2011c).

Em sua página7 o autor trás à tona diversas questões polêmicas a respeito do projeto e ar-

gumenta diversas decisões do novo projeto. Devido a importância do projeto Mongrel na co-

munidade de desenvolvedores Ruby on Rails, muito ainda irá se falar sobre esta nova versão.

4.3 Servidores Web de múltiplo propósito

Atualmente existem diversas opções de servidores que podem ser utilizados para rodar

aplicações Ruby on Rails. Neste trabalho estão sendo citados os principais, mais conhecidos e

relevantes ao problema que está sendo abordado.

4.3.1 Apache2.28

O mais tradicional e conhecido servidor Web do mundo, projeto mantido pela fundação

Apache, foi criado em 1995 por Rob McCool, funcionário na época do NCSA (National Cen-

ter for Supercomputing Applications).

Servidor compatível com o protocolo HTTP versão 1.1, sua funcionalidades são mantida

através de uma estrutura de módulos, permitindo inclusive que sejam expandidas através de

sua API Wikipédia (2010h).

Nesse contexto algumas soluções para Ruby e Ruby on Rails surgiram: mod_ruby,

mod_rails/mod_rack.

4.3.1.1 mod_ruby

Incorpora o interpretador Ruby as extensões do servidor Apache, permitindo que scripts

Ruby possam ser executados nativamente pela interface CGI do Apache, disponibilizando a

API do Apache para ser utilizada dentro dos scripts Ruby. A vantagem dessa abordagem está

7 Página oficial do projeto Mongrel2: http://mongrel2.org

8 Apache httpd está disponível em: http://httpd.apache.org

Page 31: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

29

no fato de que ao utilizar o mod_ruby (no lugar de uma abordagem com CGI ou FastCGI),

você conseguirá iniciar mais rapidamente esses scripts.

Apesar do mod_ruby ser citado neste trabalho, ele não é utilizado para rodar aplicações

Rails, por não possuir uma performance tão boa quanto esperada, e pela sua arquitetura difi-

cultar a utilização em ambientes que possuam mais de uma aplicação Rails por máquina,

muto comum em serviços de hospedagem compartilhada.

O grande problema dessa solução é que ao compartilhar o interpretador com mais de uma

aplicação, elas acabam por tentarem se sobrepor, umas as outras, em tempo de execução, cri-

ando diversos comportamentos indesejados, segundo LAI (2011).

Basicamente uma evolução natural a esta solução é o caso do Phusion Passenger como

citado a seguir.

4.3.1.2 Phusion Passenger (mod_rails/mod_rack)9

Solução praticamente obrigatória para ser utilizada em conjunto com servidores Apache.

Facilita o deployment de aplicações web escritas em Ruby, de forma a precisar apenas colocar

os arquivos no servidor, sem qualquer tipo de alteração específica, que ele se responsabiliza

por iniciar a aplicação corretamente.

Projetado desde o principio com questões de performance, estabilidade e segurança em

mente. Se utilizado em conjunto com o “Ruby Enterprise Edition”10 consegue economizar em

média 33% de memória RAM. Phusion (2010)

A partir da versão 3.0 possui além do suporte ao Apache, suporte ao Nginx bem como in-

tegração com outras soluções utilitárias como Bundler (gerente de dependências) e o RVM

(Ruby Version Manager, que permite rodar em um mesmo servidor, aplicações com versões

diferentes do Ruby).

9 Phusion Passenger está disponível através do rubygems. Instruções para instalação podem ser encontradas no site oficial: http://www.modrails.com/

10 Fork do interpretador do Ruby na versão 1.8.7, criado pela Phusion, onde implementa uma série de aperfeiçoamentos fo-cados em performance e melhor utilização de recursos da máquina. Disponível em: http://www.rubyenterpriseedition.-com/

Page 32: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

30

4.3.2 Nginx11

Trata-se de um servidor web, leve, de alta performance que também pode funcionar como

um proxy reverso, Wikipédia (2010i), para ser utilizado em balanceamento de cargas de clus-

ters Mongrel. Possui performance incomparável com qualquer outra solução no que diz res-

peito a servir conteúdos estáticos como imagens, arquivos javascripts, CSS, videos, etc.

Recentemente, com o lançamento do “Phusion Passenger 3”, o Nginx também passou a

ser suportado pela solução, substituindo completamente as implantações com cluster Mon-

grel.

A maior diferença de performance se dá pela sua arquitetura, segundo CHILTON (2011)

construída em um modelo baseado em eventos, não bloqueante (non-blocking event-based

model), capaz de servir mais de 10.000 reqs/s utilizando o mínimo de recursos possível da

máquina.

4.3.3 Lighttpd12

Servidor web de código aberto, projetado e otimizado para ambientes de alta performan-

ce, com baixo consumo de memória (low memory footprint) comparado com outros servido-

res web, e diversos recursos Lighttpd (2011).

Está em produção em diversos sites da web 2.0 de grande porte como YouTube, Wikipé-

dia, e Meebo. Segundo descrição no próprio site, sua infra-estrutura de I/O de alta velocidade,

permite escalar melhor em varias vezes, com o mesmo hardware, que outras soluções13.

A execução de aplicações Rails é feita via FastCGI.

11 Disponível em: http://nginx.org/

12 Disponível em: http://www.lighttpd.net/

13 Existe um benchmark e diversas informações e comparativos em: http://www.lighttpd.net/benchmark/

Page 33: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

31

4.3.4 Cherokee14

Cherokee é um servidor web de alta performance, flexível e fácil de instalar e configurar.

Tem suporte para uma gama enorme de recursos e tecnologias que passa por: FastCGI, SCGI,

PHP, CGI, uWSGI, SSI, conexões criptografadas com TLS e SSL, virtual hosts, autenticação,

“on the fly encoding”, balanceamento de carga, balanceamento de base de dados, proxy HTTP

reversa, traffic shapper, streaming de video, e mais ORTEGA (2011).

O grande diferencial, além dos recursos e da alta velocidade, comparável ao lighttpd e ao

nginx, é a interface de configuração através do cherokee-admin, que permite instalar uma

gama variada de aplicações web conhecidas como Wordpress, Moodle, etc, como também

configurar desde questões simples a configurações avançadas de maneira muito simplificada.

Possui também suporte a configurar um Virtual Host para hospedar uma aplicação Rails,

a poucos clicks de distância.

4.4 Servidores de Banco de Dados Relacional

Tradicionalmente três bancos de dados são suportados pelo framework, são eles o SQL

Lite, MySQL e PostgreSQL.

É possível utilizar outros SGBDs, com a instalação de extensões e plugins que ofereçam

a integração deles com o framework.

4.4.1 SQL Lite

Trata-se de uma solução simplista de armazenamento de dados relacional, mais leve e

com poucos recursos, utilizado principalmente por aplicações pequenas ou em ambiente de

testes, onde rodar um SGBD dedicado não é uma opção.

É composto por uma biblioteca em linguagem C, que implementa um banco de dados

SQL embutido. A biblioteca lê e escreve diretamente para um arquivo no disco, que contém

toda a base de dados.

14 Disponível em: http://www.cherokee-project.com/

Page 34: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

32

Não é recomendável utilizá-lo em aplicações que recebam muitos acessos, que necessi-

tem armazenar quantidade grande de dados ou que trabalhem com alta concorrência. Wikipé-

dia (2011d)

4.4.2 MySQL

É um Sistema de Gerenciamento de Banco de dados (SGBD) que utiliza a linguagem

SQL como interface. É atualmente um dos bancos de dados mais populares, com mais de 10

milhões de instalações pelo mundo.

Disponível atualmente na versão 5.5.x, oferece suporte para praticamente todas as plata-

formas atuais. Possui drivers e módulos de interface para diversas linguagens de programação

como Delphi, Java, C/C++, C#, Visual Basic, Python, Perl, PHP, ASP e Ruby.

Além de ser Software Livre (GPL), oferece excelente desempenho e estabilidade, sendo

utilizado inclusive em sistemas de missão crítica. Oferece recursos de controle transacional,

triggers, stored procedures e functions. Possui suporte a replicação e dispõe de uma versão

especifica para rodar de forma clusterizada (MySQL Cluster) Wikipédia (2011e).

4.4.3 PostgreSQL

Também conhecido apenas por “Postgres”, é um sistema de gerenciamento de banco de

dados objeto-relacional (ORDBMS). Seu código fonte é disponibilizado sob licença MIT, o

que também o torna um software livre.

Não é controlado por uma única companhia e sim por uma comunidade global de desen-

volvedores e outras companhias que são responsável pelo desenvolvimento e manutenção do

mesmo.

Possivelmente o servidor de banco de dados em software livre mais poderoso existente,

seus recursos muitas vezes são comparados as soluções da ORACLE, e sua performance

comparada a bancos muitas vezes mais simples, o que o coloca no “melhor dos dois mundos”.

Utilizado por alguns grandes nomes como Yahoo, MySpace, Sony Online, Skype, Sun

xVM e pela estação espacial internacional Wikipédia (2011f).

Page 35: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

33

4.5 Servidores de Banco de Dados NoSQL

4.5.1 Introdução

Comumente conhecidos como bancos de dados orientados a documento, ou bancos de

dados chave-valor são bancos de dados não relacionais em sua maioria altamente escaláveis e

de alta performance. Eles não possuem um esquema de dados fixos e alguns se baseiam no

conceito de “chave-valor”, onde, como em uma estrutura de hash, ao passar a “chave”, você

consegue recuperar o valor armazenado, seja ele de qual tipo for (número, texto, arquivo mul-

timídia, etc).

Alguns dos mais conhecidos que podem ser citados são: MongoDB, CouchDB, Cassan-

dra, Hadoop Database, Hypertable e Memcachedb Wikipédia (2010j).

4.5.2 MongoDB15

Combina características das bases de dados orientadas a documentos (rápido e altamente

escalável) com a das bases de dados relacionais tradicionais (que provém mecanismos pode-

rosos de pesquisa e diversas funcionalidades).

Algumas de suas principais características, segundo 10gen (2010):

• Estrutura de armazenamento orientada a documentos16

• Suporte completo a utilização de índices

• Suporte a replicação e alta disponibilidade

• Sharding automático

• Mecanismos de consulta que não apenas “chave-valor”

• Suporte a operações de Map/Reduce

15 MongoDB está disponível em: http://www.mongodb.org/

16 Utiliza o conceito de schemas dinâmicos

Page 36: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

34

• GridFS – Permite armazenar arquivos de qualquer tamanho, que a aplicação

se encarrega em dividir os pedaços e em como armazenar/recuperar.

4.5.3 CouchDB17

Base de dados orientada a documento que pode ser consultada e indexada a partir de ins-

truções e chamadas seguindo o padrão MapReduce. O acesso aos dados é feito através de

uma conexão HTTP utilizando webservice RESTful e JSON.

4.5.4 Cassandra18

Baseado no Amazon Dynamo e Google BigTable, trazendo o melhor dos dois mundos.

Utilizada por alguns dos grandes nomes da Web 2.0: Digg, Twitter, Reddit, Facebook

sendo este ultimo, seu criador original. O maior cluster em atividade, segundo Apache Funda-

tion (2011), conta com 150 máquinas e armazena 100TB de dados.

4.5.5 Hadoop database19

Sua arquitetura é bastante inspirada na solução proprietária do Google, a BigTable. A in-

terface de acesso aos dados é feito através de um webservice RESTful.

4.5.6 Redis20

Banco de dados tipo chave-valor. Podem armazenar dados do tipo: string, hashes, listas,

sets, e sorted sets.

Ficou difundido dentro da comunidade de programadores Rails, pela solução Resque, que

funciona como um escalonador de jobs. Porém sua utilização não se restringe somente a co-

munidade Rails. É utilizado atualmente, segundo Citrusbyte (2011) por: Mercado Livre, gi-

thub, craiglist, guardian.co.uk, Blizzard, Digg, Disqus, Stackoverflow entre outros.

17 CouchDB está disponível em: http://couchdb.apache.org/

18 Cassandra: http://cassandra.apache.org/

19 Hadoop database está disponível em: http://hbase.apache.org/

20 Resque está disponível em: http://redis.io/

Page 37: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

35

4.6 Implementações da linguagem Ruby

“Ruby é uma linguagem de programação interpretada multiparadigma, de tipagem dinâmica e forte, com gerenciamento de memória automático, originalmente plane-jada e desenvolvida no Japão em 1995, por Yukihiro "Matz" Matsumoto, para ser usada como linguagem de script. Matz queria uma linguagem de script que fosse mais poderosa do que Perl, e mais orientada a objetos do que Python. Ruby suporta programação funcional, orientada a objetos, imperativa e reflexiva. Foi inspirada principalmente por Python, Perl, Smalltalk, Eiffel, Ada e Lisp, sendo muito similar em vários aspectos a Python. Atualmente, Ruby é a 10º linguagem de programação mais popular do mundo, de acordo com o Índice Tiobe.” Wikipédia (2011g)

Baseadas na implementação referência, também conhecida como “Ruby MRI” (Matz

Ruby Interpreter) ou “CRuby” (já que é escrita em C), diversas outras implementações, com

motivações diferentes foram realizadas.

A implementação oficial hoje possui duas “major versions” que são amplamente utiliza-

das e recebem atualização, a versão 1.8.x e 1.9.x, que estão, respectivamente, nas versões

1.8.7 e 1.9.2 atualmente.

Todas as outras implementações da linguagem, buscam compatibilidade total com pelo

menos uma delas, inicialmente, almejando compatibilidade sempre com a versão mais nova

da implementação MRI.

As existentes e conhecidas atualmente são:

• Ruby MRI

• YARV

• REE

• JRuby

• IronRuby

• Rubinius

• MacRuby

• HotRuby

• MagLev

YARV foi uma máquina virtual baseada em bytecode criada originalmente com a finali-

dade de aumentar a performance da linguagem. Ela foi englobada totalmente na implement-

ção oficial do Ruby 1.9 Wikipédia (2011h).

Page 38: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

36

O Ruby Enterprise Edition (REE) é um fork do MRI 1.8.7 realizado pela Phusion, que

objetiva resolver alguns dos problemas da versão 1.8.x relacionados a performance e consu-

mo de memória, para aplicações servidoras, basicamente focado em rodar Ruby on Rails.

JRuby é uma implementação escrita em Java, desenvolvida pelo JRuby Team. Ela é alta-

mente integrada com o Java, que permite embarcar o interpretador em qualquer aplicação

Java e permitir comunicação de duas vias entre o código Ruby e o código em Java (semelhan-

te a abordagem do Jython com a linguagem Python) Wikipédia (2011i).

Pelo fato do JRuby rodar em cima da JVM, ele também é multiplataforma (roda em qual-

quer sistema operacional ou máquina física que a JVM for capas de operar).

Além da integração com a linguagem Java, o fato de rodar na JVM confere a essa imple-

mentação uma ótima performance, disputando o primeiro lugar com a implementação oficial.

O IronRuby é a contrapartida para plataforma .NET, oferecendo benefícios semelhantes a

implementação JRuby, dentro deste outro universo.

Gráfico 2: Tempo de execução do benchmark realizado pelo "Programming Zen"

Page 39: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

37

O MacRuby é uma implementação em Objective-C integração com o framework “Core-

Fundation” do MacOS X, desenvolvida pela Apple. Baseada na versão 1.9, suporta compila-

ção ahead-of-time e just-in-time (JIT).

Possui suporte ao Interface Builder e vem com a biblioteca HotCocoa, que simplifica a

implementação na biblioteca gráfica do Mac OS X (Cocoa) Wikipédia (2011j).

Rubinius é uma outra implementação do Ruby, seguindo uma arquitetura um pouco dife-

rente da oficial, englobando LLVM. Seu desenvolvimento não está tão avançado quanto as

demais implementações.

Por fim a MagLev (referência clara ao trem de alta velocidade), é uma implementação

desenvolvida pelo GemStone, que almeja tratar o problema de escalabilidade de aplicações

Ruby, na própria VM. No site oficial21 o slogan é “Ruby that scales”, e a solução que eles

propõem é acrescentar um recurso de persistência dos objetos nativamente na VM, em con-

junto com um cache compartilhado e distribuído.

Essa implementação é a única que não possui uma licença livre, e é baseada numa má-

quina virtual da própria empresa, criada inicialmente para rodar aplicações SmallTalk. Ainda

está em estágio Alpha Wikipédia (2011k).

4.6.1 Comparativos de performance

Existe uma grande quantidade de comparativos de performance entre as diversas imple-

mentações, disponíveis em sites e blogs de desenvolvedores de cada uma das implementa-

ções, bem como programadores e entusiastas da linguagem.

Um mais recente, disponibilizado pelo site Programming Zen22 analisa as principais im-

plementações. No artigo é possível verificar a metodologia utilizada bem como os dados bru-

tos e mais informações sobre o teste.

21 http://ruby.gemstone.com/

22 http://programmingzen.com/2010/07/19/the-great-ruby-shootout-july-2010/

Page 40: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

38

Os resultados mostrados no Gráfico 2 de tempo de execução do benchmark e consumo de

memória, ilustram bem a diferença de performance e consumo de memória das diferentes im-

plementações.

IronRuby teve o pior desempenho, seguido pela versão Ruby MRI 1.8. É possível notar

que o REE de fato mostra um ganho de performance em relação a implementação padrão,

mas é muito mais lento que a série 1.9.x e JRuby.

Vale comentar que, apesar do MagLev estar presente nesse benchmark, ele ainda não é

capaz de rodar aplicações Rails, portanto saindo do escopo dessa análise.

Page 41: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

39

Page 42: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

40

Nessa métrica demonstrada pelo Gráfico 3, a disputa é claramente entre Ruby 1.9.2 e

JRuby, sendo que o segundo consegue uma ligeira vitória. Já analisando pelo consumo de me-

mória, o pequeno ganho de performance que a implementação JRuby forneceu, não valeu a

pena pela quantidade de recursos necessários para sua execução e claramente a versão 1.9.2.

Vale ressaltar que segundo este teste, o REE apresentou um consumo de memória considera-

velmente maior que a MRI, algo totalmente não esperado.

Sendo assim, pode-se concluir que a melhor implementação até o momento (consideran-

do performance e consumo de memória) é a oficial (MRI) utilizando a versão 1.9.2.

Gráfico 3: Consumo de memória do benchmark realizado pelo "Programming

Zen"

Page 43: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

41

4.7 Problemas

Pensando em situações reais, vamos estudar os seguintes cenários de problemas, por se-

rem considerados mais genéricos e de certa forma universais, sendo que não é foco deste tra-

balho tentar esgotar todos os tipos possíveis de problemas de escalabilidade que uma aplica-

ção possa ter.

1. Aplicação com numero crescente de acessos

2. Aplicação com necessidade de processamento crescente de informações

3. Aplicação com necessidade crescente de armazenamento de dados ou arquivos

4. Aplicações que necessitem de nova instalação para cada novo endereço/propósito

Cada um destes pontos será tratado individualmente, mas com a consciência de que não são

mutuamente excludentes e podem estar presentes em cenários reais uma união de mais de um

deles.

4.7.1 Número crescente de acessos

Em uma situação genérica, um número crescente de acessos impacta no aumento do pro-

cessamento, para atender as requisições, consumo memória, já que mais instâncias da aplica-

ção precisam estar disponíveis e um aumento na utilização da infraestrutura de rede.. Depen-

dendo da natureza da aplicação pode exigir mais em armazenamento de dados, sejam relacio-

nais ou não.

Dos quatro itens citados a cima, três fazem parte do foco deste trabalho: aumento do pro-

cessamento, consumo de memória, armazenamento de dados.

Para cada tipo de aplicação, deve-se analisar quais dos itens acima são os gargalos e tra-

tá-los de acordo com o caso.

Para esse problema pode se tratar utilizando escalabilidade vertical, aumentando os re-

cursos que estiverem em falta na máquina, até o ponto em que for financeiramente viável.

Desse ponto em diante, a aplicação precisa ser escalada horizontalmente.

Page 44: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

42

4.7.2 Necessidade crescente de processamento de informações

Alguns tipos de aplicação apresentam desafios de escalabilidade no que se refere ao pro-

cessamento crescente de informações. O aumento pode estar relacionado com o aumento do

número de acessos ou não.

Entram no escopo, por exemplo aplicações que trabalham com estatísticas em cima de

grande volume de dados, geram relatórios, sumarizam informações. Um exemplo que pode

ser citado é o Google Analytics, ferramenta que coleta dados dos usuários que navegam em

determinados portais, para extrair informações sobre a sua utilização, origem dos acessos en-

tre uma outra infinidade de métricas.

Outro exemplo pode ser um repositório de fotos ou vídeos online, onde os diversos usuá-

rios enviam seus arquivos e os mesmos necessitam passar por etapas de processamento seja,

para conversão entre formatos, ou simplesmente gerar miniaturas.

4.7.3 Aplicações com necessidade crescente de armazenamento de dados ou

arquivos

Podemos considerar, que este tipo de aplicação pode incluir armazenamento em base de

dados, relacional ou não, bem como espaço em disco para armazenamento de arquivos relaci-

onados a aplicação (ex: um serviço responsável por armazenar fotografias digitais, ou mesmo

que forneça um espaço de armazenamento de arquivos do usuário).

Para o primeiro caso, a abordagem vai depender de qual SGBD está sendo utilizada.

Caso ele ofereça algum suporte nativo para funcionalidade de sharding, é através desse supor-

te que poderemos fazer a nossa base de dados crescer e ser dividida entre mais de uma máqui-

na, sem necessidade de alterar a lógica da nossa aplicação.

Caso não exista o suporte pelo SGBD, o sharding deverá ser implementado utilizando al-

guma lógica definida na aplicação.

Page 45: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

43

4.7.4 Aplicações Multi-Site

Como citado no capítulo sobre problemas genéricos de escalabilidade, esse tipo de apli-

cação, apresenta-se como um problema de escalabilidade, já que cada nova instalação estará

ocupando processador, consumindo memória e sendo instanciada para cada “nova instância”.

Um exemplo de serviço existente, que foi programado utilizando o framework Ruby on

Rails e contorna programaticamente essa necessidade de instalação, de uma maneira seme-

lhante ao Wordpress citado anteriormente, é o Shopify23.

4.8 Soluções

As soluções apresentadas aqui servirão como referência para solucionar cada um dos pro-

blemas de escalabilidade que atingem uma aplicação em Ruby on Rails. Além das questões

levantadas no capítulo anterior, gargalos na aplicação podem impactar negativamente na per-

formance e consequentemente na capacidade da solução escalar, e devido a natureza deste

problema, não existe um guia definitivo, porém diversas há sugestões de ferramentas que au-

xiliam a identificar esses gargalos.

4.8.1 Arquitetura escalável para aplicações com muitos acessos

Dividiremos a análise em dois grupos: aplicações web com pouco acesso a banco de da-

dos, e aplicações web com muito acesso a banco de dados.

4.8.1.1 Aplicação web pouco acesso a banco de dados

No primeiro cenário, pode-se considerar desprezível para o tamanho do problema o fator

de acesso a base de dados. Considera-se que o cache interno de consultas, por sí só é suficien-

te não necessitando nenhuma intervenção maior.

Basicamente o que é necessário nesta situação é escalar horizontalmente os servidores

Web. Para tal sugere-se a seguinte configuração:

23 Serviço de lojas online, onde é possível, após se registrar, criar uma loja online totalmente customizada para sua empresa. http://www.shopify.com/

Page 46: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

44

• Load Balancer (balanceador de carga)

• Cluster de servidores Web

• Servidor de banco de dados

• Servidor memcached

O load balancer será responsável por receber as requisições e distribuir para as máquinas

no cluster de servidores Web. Pode ser utilizado hardwares específicos, que realizam a distri-

buição em vários níveis da camada OSI, desde os mais baixos até nível de aplicação, ou atra-

vés de soluções em software, que podem ser desde aplicações dedicadas, a solução IPVS que

utiliza recursos disponíveis no próprio kernel do Linux ou até mesmo, um servidor Web que

possua essa funcionalidade como o Nginx.

O cluster de servidores Web deve ser composto por uma das soluções de servidores web

para Ruby on Rails ou de múltiplo propósito junto com uma solução para carregar a aplicação

(como por exemplo o Passenger).

Cada máquina do cluster deverá ter uma cópia idêntica do código que está sendo execu-

tado da aplicação, e, caso haja a necessidade de salvar arquivos fisicamente no disco, envia-

dos pelos usuários da aplicação, este deve ser salvo em um local de armazenamento comparti-

lhado por todas máquinas do cluster, como por exemplo um diretório montado com NFS24.

A aplicação deverá configurar um ou mais “asset servers25”, para disponibilizar o conteú-

do estático da aplicação de forma mais performática e aumentar o paralelismo da transferên-

cia dos recursos utilizados na página, pelos navegadores. Os “asset servers” podem ser confi-

gurados nos próprios servidores de múltiplo propósito, bastando apenas que seja configurado

corretamente um ou mais VirtualHost.

O servidor de Banco de Dados poderá dividir a mesma máquina com o memcached, se

ele não for o gargalo de escalabilidade da aplicação e se houver memória RAM livre suficien -

te.

24 http://en.wikipedia.org/wiki/Network_File_System_(protocol)

25 Asset Servers são definidos em uma configuração do framework, onde aponta o conteúdo estático da aplicação para um outro endereço (geralmente um subdomínio ou vários).

Page 47: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

45

O memcached será responsável por compartilhar o cache entre as aplicações replicadas

no cluster Web e disponibilizar os dados de sessão entre todos servidores, para que qualquer

uma das máquinas possam responder as requisições de maneira transparente.

Com essa arquitetura, para atender um volume crescente de acessos, basta aumentar a

quantidade de máquinas no cluster Web (escalabilidade horizontal) e/ou utilizar máquinas

com mais recursos de memória e processamento a fim de suportar mais instâncias da aplica-

ção rodando simultaneamente por máquina.

Eventualmente com um volume muito grande de acessos, pode ser necessário realizar in-

tervenção no load balancer, como substituir a solução em software por solução em hardware.

4.8.1.2 Aplicação web com muito acesso de leitura banco de dados

Além do que foi relatado no cenário anterior, para este cenário, se faz necessário alguns

cuidados em relação ao servidor de banco de dados, e portanto sugere-se a seguinte configu-

ração:

• Load Balancer (balanceador de carga)

• Cluster de servidores Web

• Cluster de servidores de banco de dados

• Servidor memcached

Nesta configuração, ou o servidor de banco de dados provê uma forma de distribuição de

carga sem que seja necessário alteração na aplicação, ou a aplicação precisa ter noção da exis-

tência de mais de um servidor de banco de dados para que ela possa realizar o balanceamento

das requisições ela mesma.

Usando o MySQL como exemplo, é possível colocar as diversas máquinas em cluster

com configuração Master – Master, ou Master – Slave. Sendo que a primeira tem limite de

escalabilidade bem menor que a segunda.

Page 48: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

46

Ao utilizar a ferramenta do mysqlproxy, ele intercepta as requisições e identifica quais es-

tão solicitando operações de leitura (SELECT) e quais estão solicitando alguma operação de

escrita (INSERT, UPDATE, DELETE, TRUNCATE, etc) e direciona para servidores Slave e

Master respectivamente.

O ponto positivo dessa solução é que não é necessário nenhuma alteração na aplicação,

basta apontar ela para o endereço do mysqlproxy. O ponto negativo é que ele vira um ponto

único de falha e pode se tornar também o gargalo.

Uma solução menos eficiente, que ainda não requereria alterações seria, em uma replica-

ção Master – Master, apontar cada grupo de máquinas para um servidor diferente pré-defini-

dos nas configurações de acesso a banco.

A desvantagem dessa solução é óbvia, já que não garante uma distribuição uniforme do

acesso ao banco podendo gerar uma situação em que alguns servidores estejam sobrecarrega-

dos enquanto outros estejam sendo subutilizados.

A solução mais adequada, exige a instalação de um plugin na aplicação, funciona tanto

com uma configuração Master – Master, quanto com a Master – Slave.

Atualmente o plugin que possui melhor compatibilidade com o Rails 3.0 é o Octopus26.

Este, além de permitir fazer o balanceamento de carga do banco de dados e o suporte a dife-

renciação de acesso master ou slave, disponibiliza uma API para trabalhar com mais de uma

máquina de banco de dados dentro do Rails.

4.8.2 Aplicações que necessitem processar muitas informações

A regra pra qualquer tipo de processamento de informação mais intenso ou demorado, é

ser realizado fora do tempo de execução de uma requisição.

Isso pode ser feito com algumas estratégias:

• Processamento assíncrono

• Cronjobs

26 Disponível em: https://github.com/tchandy/octopus

Page 49: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

47

• Aplicação dedicada a este propósito

Para o primeiro caso, pode-se utilizar a abordagem de disparar um processamento, no

tempo de uma requisição web, que aconteça em segundo-plano, ou agendar a execução do

processamento em uma fila, desacoplado a execução da requisição na aplicação.

Dependendo da natureza da aplicação, a resposta deste processamento pode aparecer fu-

turamente na aplicação, pode utilizar um estratégia combinada com AJAX, a aplicação pode

enviar um e-mail avisando que o processamento foi concluído, etc. Não existe modelo fixo

para isso, e vai depender muito de caso pra caso.

Caso a escolha seja enviar o processamento para uma fila, existe diversas soluções para

Rails, as mais conhecidas e utilizadas são:

• DelayedJob27

• BackgroundRB28

• Reque29

• Navvy30

Cada um possui funcionalidades distintas e características específicas, a escolha de uma

delas precisa passar por um levantamento prévio dos requisitos.

4.8.3 Aplicações com necessidade de armazenar muitos dados/arquivos

Se o problema fundamental da aplicação estiver relacionado com armazenar grandes vo-

lumes de dados em um SGBD, a solução vai ser a mesma utilizada para qualquer tipo de apli-

cação, seja web ou não, que tenha a mesma necessidade, e resume-se a escalar verticalmente

a capacidade de armazenamento, através de soluções de storage, lvm ou utilizar alguma confi-

guração de divisão dos dados (sharding) do próprio SGBD, como no caso do MongoDB.

27 Disponível em: https://github.com/collectiveidea/delayed_job. Screencast/tutorial disponível em: http://railscasts.com/episodes/171-delayed-job

28 Disponível em: https://github.com/mtylty/backgroundrb-rails3

29 Disponível em: https://github.com/defunkt/resque

30 Disponível em: https://github.com/jeffkreeftmeijer/navvy

Page 50: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

48

Quando o SGBD não possui um suporte nativo e transparente para o problema, este ne-

cessitará de alguma intervenção em código na aplicação, seja para que a própria implemente a

lógica para distribuir e recuperar esses dados, ou para que ela se integre com a solução do

SGBD.

O Octopus31 oferece, além do suporte a replicação de bases, ferramentas para trabalhar

com Sharding em banco de dados, permitindo trabalhar com vários servidores de banco de

dados, e definir na aplicação a lógica para acessar/recuperar esses dados.

Além dele, existe mais algumas soluções focadas neste problema, que são elas:

• DbCharmer32

• MultiDb33

4.8.4 Aplicações Multi-Site

Para construir uma aplicação Multi-Site, seja em Rails ou em qualquer outro framework,

é necessário ter em mente desde o início do projeto o objetivo. Utilizaremos como exemplo o

Wordpress MU, para analisar as soluções adotadas e transpô-las para realidade do Rails.

4.8.4.1 Instâncias da aplicação Multi-Site

Uma aplicação tradicional possui sua “identidade” atribuída ao conjunto de informações

que são configuradas no momento da sua instalação/implantação, tais quais:

• Dados de acesso ao banco de dados

• Caminhos do sistema operacional para recursos da aplicação

• Layouts, templates, customizações etc.

O conceito de individualidade para uma aplicação Multi-Site, precisa ser virtual, e não

mais físico.

31 Disponível em: https://github.com/tchandy/octopus

32 Disponível em: https://github.com/kovyrin/db-charmer

33 Disponível em: https://github.com/schoefmax/multi_db

Page 51: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

49

A individualização, para o lado do cliente da aplicação se dá pelo endereço da URL, que

pode ser um subdomínio da aplicação ou um domínio próprio.

Do lado do servidor, algumas estratégias podem ser utilizadas:

• Para cada domínio/subdomínio, utilizar uma configuração diferente de acesso a base

de dados

• Utilizar uma mesma conexão a base de dados, porém gerar conjunto de tabelas dife-

rentes para cada domínio/subdomínio (solução adotada pelo Wordpress MU)

• Utilizar um conjunto único de tabelas, e acrescentar uma chave extra em todos os con-

juntos de dados referenciando ao domínio/subdomínio.

A primeira opção apresenta problemas de performance, já que será necessário abrir um

número muito grande de conexões a bancos diferentes em espaços de tempos muito curtos.

Reduzindo diversas estratégias de otimização presentes no framework como utilização de

Pool de conexões, cache de consultas, etc.

A segunda opção não funciona muito bem de maneira transparente com ActiveRecords,

portanto não sendo ideal também.

A terceira opção é a que mais se adequa ao funcionamento do Ruby on Rails e portanto

vai ser a indicada.

Existe um Screencast34 do Railscasts que explica passo a passo como construir uma apli-

cação modelo utilizando subdomínios como identificação da “instância virtual” da aplicação e

utilizando o modelo de acrescentar uma chave referenciando o domínio em cada tabela.

No video, é citado um plugin35 que simplifica alguns procedimentos necessários e provê a

integração com as rotas do Rails.

34 Video tutorial, disponível em: http://railscasts.com/episodes/123-subdomains

35 Subdomain-Fu, disponível em: https://github.com/mbleigh/subdomain-fu

Page 52: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

50

4.8.4.2 Contas de usuário

O segundo problema desse tipo de aplicação é escolher qual abordagem será dada para

criação de contas de usuário.

Pode se optar pela abordagem de, ter um cadastro global, para identificar cada

“instância” (subdomínios) e em cada aplicação utilizar uma abordagem de cadastros locais.

Nessa arquitetura, não é necessário nenhum tipo de cuidado extra em relação aos cadas-

tros locais, já que eles serão gerenciados pelo dono daquela instância, e não serão comparti-

lhados.

A outra abordagem é utilizar um cadastro compartilhado de usuários e trabalhar com per-

missões por instância virtual da aplicação. Esse modelo exige um pouco mais de cuidado, já

que as contas podem ser compartilhadas entre mais de uma instância, e portanto é necessário

um controle maior de permissões para evitar que uma alteração de um “Administrador” de

uma instância, prejudique inadvertidamente o usuário que é compartilhado com outra instân-

cia.

Existem outras dificuldades envolvidas relacionadas a privacidade, tais quais:

• Qual o procedimento para incluir um usuário existente?

◦ Utilizar um sistema de convite, com necessidade de confirmação?

◦ Acrescentar imediatamente mesmo sem confirmação?

◦ Listar todas as pessoas cadastradas e permitir a seleção a partir dessa lista global?

• Como lidar com dados pessoais?

◦ Permitir que o administrador de uma instância tenha acesso?

◦ Controlar a possibilidade de acesso por um sistema de permissões?

Essas são apenas alguns exemplos que vão muito além da arquitetura da aplicação mas

são ainda sim importantes.

Page 53: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

51

4.8.4.3 Gerenciamento

A principal vantagem de se construir uma aplicação Multi-Site está em poder gerenciar

diversas “instalações” em uma só. Pelo modelo proposto, o gerenciamento global se torna

simplificado, já que a aplicação tem acesso a todas as tabelas de maneira facilitada, permitin-

do através de alguns filtros de consulta, poder extrair todas as informações que possam ser

necessárias, bem como permitir funcionalidades como Administrador Global, com acesso a

todas as instâncias virtuais, etc.

Neste ponto não existe nenhum tipo de limitação do que pode ser feito.

4.8.4.4 Arquivos físicos do usuário e templates

Supondo que a aplicação permita envio de arquivos ao servidor, é necessário encontrar

uma forma de separar por instância esses arquivos.

O modelo utilizado pelo Wordpress MU foi armazenar todos os arquivos do usuário em

uma estrutura de pastas que segue o seguinte padrão:

/blogs.dir/$id

Dessa forma, cada instância é identificada pelo seu ID no banco de dados e pode acessar

os arquivos a partir desse caminho.

Existe um plugin36 que consegue fornecer essa funcionalidade bem como a possibilidade

de templates diferenciados por instância virtual, porém não é compatível com o Rails 3.0. Até

o momento não existe um outro plugin que forneça funcionalidades similares, sendo assim

necessário implementar diretamente no código da aplicação essas peculiaridades.

4.8.4.5 Conclusão

O suporte a aplicações Multi-Site é ainda incompleto e não existem soluções atualizadas

que contemplem a maioria das necessidades mais comuns desse tipo de aplicação.

36 Rails Multi-site, disponível em: https://github.com/dasil003/rails-multisite

Page 54: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

52

4.9 Como identificar gargalos (bottlenecks)

Existem diversas maneiras de se identificar gargalos em uma aplicação Rails.

Em tempo de desenvolvimento, rodando a aplicação em um servidor Webrick, o mesmo

disponibiliza inúmeras informações e métricas em tempo de execução mostrando o tempo que

os principais componentes levaram para processar uma informação. Dessa forma é simples

verificar se a lentidão está no processamento das consultas do banco, ou se a interface está re-

alizando processamento demais para conseguir renderizar a página de saída.

Uma maneira um pouco mais avançada seria acoplar à aplicação alguma ferramenta ou

serviço (SaaS) que consiga realizar uma análise mais detalhada dos gargalos e realize uma

monitoração para alertar sobre problemas que possam afetar a estabilidade ou performance da

aplicação.

4.9.1 Monitoramento e Análise de performance

Para realizar as tarefas de monitoramento, análise de performance e medições no sentido

de identificar gargalos e poder realizar ajustes finos (tunning) existe algumas ferramentas e

serviços (SaaS) que podem ser utilizados, e serão listados a seguir.

4.9.1.1 RPM (New Relic)

Nesse ponto, é interessante de citar o RPM37, uma ferramenta da empresa de consultoria

em escalabilidade NewRelic.

A ferramenta está disponível na forma de serviço online (SaaS) em versão gratuita e

paga. Na sua versão gratuita possui funcionalidades básicas de monitoramento, que podem

ser úteis para se ter algumas métricas da aplicação em ambiente de produção.

Ela também disponibiliza em caráter “trial”, durante os 7 primeiros dias, o acesso a todas

as funcionalidades da versão “Gold”, que além dos recursos de monitoramento, registra fa-

lhas, faz análise da causa de diversos problemas e falhas e disponibiza análises relacionados

37 Ferramenta está disponível em: http://www.newrelic.com. Será necessário instalar uma gem para coletar os dados direta-mente da aplicação.

Page 55: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

53

a: escalabilidade, banco de dados, transações, carga, etc, sugerindo medidas que podem ser

tomadas para solucionar pontos negativos apontados.

4.9.1.2 Union Station38

Atualmente em fase Beta, feita pelos mesmos criadores da solução Passenger para deploy

de aplicações Rails/Rack.

O forte da aplicação é a integração direta com o Passenger, que fornece dados detalhados

da execução da aplicação ao Union Station. É possível utilizá-lo como ferramenta de monito-

ração da aplicação para capturar erros de execução em produção, bem como identificar gargá-

los.

Não possui opção de conta gratuíta, porém, durante o período Beta, é possível utilizar to-

das as opções de contas disponíveis para avaliar os recursos, sem custo algum.

38 Disponível em: http://www.unionstationapp.com/

Page 56: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

5 SIMULAÇÕES

As simulações que serão executadas, pretendem fornecer dados para avaliar com seguran-

ça os principais componentes que influenciam a escalabilidade de uma aplicação, e poder ser-

vir de modelo para a escolha de uma dessas arquiteturas ao iniciar um novo projeto.

Como parte da proposta dessas simulações, pela sua natureza genérica, elas poderão ser

executadas contra projetos diferentes de aplicações, de forma auxiliar na obtenção de métricas

de performance, que poderão ser comparadas conforme diversas alterações e ajustes forem

sendo feitos na arquitetura e no projeto do sistema.

Também é objetivo dessas simulações, mostrar um comparativo de performance, nos di-

ferentes cenários e em relação a abordagem de escalabilidade horizontal e vertical.

Todos os códigos utilizados em cada cenário, bem como os dados brutos de cada simula-

ção encontram-se anexos a este trabalho.

5.1 Configuração

Para a simulação e execução dos cenários, foi optado por utilizar um ambiente virtualiza-

do, com a finalidade de facilitar a instalação e configuração das diversas máquinas que seriam

necessárias para algumas simulações.

Essa configuração também se assemelha a uma situação real, em que os serviços estão

disponibilizados em ambiente virtualizado (seja em uma infra-estrutura de cloud computing

ou não).

Page 57: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

55

São utilizadas duas máquinas físicas39 com as seguintes configurações:

• DELL XXX – 12 Gb de RAM DDR2 667Mhz, processador Intel Xeon QuadCore @

2.83Ghz (hospedagem das máquinas virtualizadas)

• Lenovo Thinkcare A62 – 4 Gb de RAM DDR 800Mhz, processador AMD Phenon II

X2 555 @ 3200Mhz (disparo dos benchmarks)

Os servidores de multi-propósito que serão utilizados são:

• Apache2

• Nginx

Os SGBDs que serão utilizados são:

• MySQL (relacional)

• MongoDB (não relacional)

Juntamente com o servidor Web, foi escolhido o Passenger (3.0.7) como responsável por

controlar as aplicações Rails e interagir com o servidor Web.

A versão do Ruby utilizada nos testes é a 1.9.2-p180.

Para a criação das máquinas virtuais, foi feito um levantamento entre os principais prove-

dores de virtualização disponíveis, e foi eleito os seguintes dois nomes: Amazon EC240,

Rackspace Cloud41, sendo o segundo escolhido para servir de modelo, pelas vantagens que ele

oferece e pelas opções de configuração42 de máquina virtual serem mais próximas das neces-

sidades de uma aplicação Rails do que as ofertadas pelo Amazon EC2.

Baseados nas opções de configuração da Rackspace Cloud, as seguintes configurações

foram definidas:

39 As máquinas foram ligadas em uma rede Gigabit Ethernet.

40 Disponível em: http://aws.amazon.com/ec2/

41 Disponível em: http://www.rackspace.com/cloud/

42 Veja comparativo entre Amazon EC2 e Rackspace em: http://www.rackspace.com/cloud/cloud_hosting_products/servers/compare/

Page 58: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

56

• Pequena: 256Mb Ram, 1 CPU

• Média: 512Mb Ram, 2 CPU

• Grande: 1024Mb Ram, 3 CPU

• Enorme: 2048Mb Ram, 4 CPU

5.1.1 Ambiente de Virtualização

A máquina que hospeda as máquinas virtualizadas recebeu a instalação de Ubuntu Linux

11.04, e utiliza a solução KVM43 (Kernel Based Virtual Machine) para realizar a virtualiza-

ção.

A criação das máquinas virtuais bem como o gerenciamento foi feito utilizando a solução

libvirt44 e a ferramenta virt-manager45.

Um guia para instalação e configuração do ambiente de virtualização semelhante ao utili-

zado, pode ser encontrado em: https://help.ubuntu.com/community/KVM.

Antes da criação das máquinas virtuais, foi feito a instalação de uma máquina virtual para

servir de modelo as demais, a fim de manter padronizado uma configuração inicial.

Esta máquina recebeu a instalação do “Ubuntu Linux Server 10.04.02 LTS”, e durante o

processo de instalação foi escolhido realizar uma “Instalação mínima para ambiente de virtua-

lização”.

Dessa forma, as máquinas virtuais foram instaladas com o mínimo possível de softwares

e com um kernel enxuto, feito especificamente para rodar dentro de uma máquina virtual.

Os seguintes pacotes do sistema operacional foram instalados: openssh-server, git-core,

build-essential, vim, htop, unzip

43 Disponível em: http://www.linux-kvm.org/

44 The Virtualization API - Disponível em: http://libvirt.org/

45 Virtual Machine Manager – Disponível em: http://virt-manager.org/

Page 59: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

57

Além do usuário padrão, foi re-definida a senha de root e configurado o login via chave

SSH, afim de facilitar o login nas máquinas, sem a necessidade de ficar digitando senha, o

que também facilitou a execução dos testes automatizados.

5.1.2 Instalação do Passenger + Ruby 1.9.2

Apesar do Passenger estar disponível nos pacotes do Ubuntu para ser instalado no Apa-

che2, não existe pacote para instalação dele no Nginx do Ubuntu. Além desse problema, a

versão que está disponível nos repositórios oficiais é a 2.2.7, e pretende-se trabalhar com a

versão 3.0.x.

Dessa forma, optou-se por realizar a instalação manual do Passenger, juntamente com a

instalação manual do Ruby 1.9.2 (que também não está disponível nos repositórios oficiais do

Ubuntu).

A instalação do Ruby foi feito utilizando a ferramenta RVM46 (Ruby Version Manager).

Segue a baixo a lista de comandos necessários para realizar as instalação (via terminal):

apt-get install curl bison openssl libreadline6 libreadline6-dev zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev libcurl4-openssl-dev

bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)

rvm install 1.9.2

rvm --default use 1.9.2

gem install passenger

A instalação do passenger para Apache ou Nginx se dá respectivamente pelos comandos:

passenger-install-apache2-module e passenger-install-nginx-module, sendo que a versão

para Nginx também gera uma instalação do Nginx, já que, devido a características dele, dife-

rente do Apache, não tem suporte a módulos “plugáveis”, necessitando então, ser recompila-

do.

46 Disponível em: http://rvm.beginrescueend.com

Page 60: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

58

5.1.3 Máquina Virtual Apache2 + Passenger

A máquina virtual destinada a rodar o servidor Apache2 com a solução do Passenger 3,

recebeu a instalação do Apache2 via pacotes do sistema operacional, e teve as seguintes con-

figurações alteradas:

# /etc/apache2/apache2.conf:

<IfModule mpm_prefork_module>

StartServers 10

MinSpareServers 10

MaxSpareServers 15

MaxClients 256

MaxRequestsPerChild 0

</IfModule>

Timeout 30

MaxKeepAliveRequests 1024

# /etc/apache2/conf.d/passenger:

PassengerMaxPoolSize 12

PassengerMinInstances 12

5.1.4 Máquina Virtual Nginx + Passenger

A máquina destinada a rodar o servidor Nginx com a solução Passenger 3, foi instalada a

partir do comando: passenger-install-nginx-module.

Teve as seguintes configurações alteradas:

user www-data;worker_processes 4;

pid /var/run/nginx.pid;

events {

worker_connections 1024;

}

tcp_nopush off;

tcp_nodelay on;

passenger_max_pool_size 12;

5.2 Metodologia

A metodologia utilizada na execução dos testes será a seguinte:

Page 61: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

59

1. Para cada novo teste, os serviços (servidor web, banco de dados, etc) das máquinas

virtualizadas serão reiniciadas e será aguardado o tempo necessário para ele se estabi-

lizar.

2. Antes de cada teste, será feito um pré-aquecimento (warm-up) a fim de iniciar as ins-

tâncias do servidor web e aplicação Rails (quando houver).

3. Os testes serão realizados por uma ferramenta construída para este trabalho, com a fi-

nalidade de automatizar o processo e garantir que ele possa ser reproduzido de manei-

ra fiel, por quem tiver interesse.

4. Os dados que serão coletados a partir do Apache Benchmark:

◦ arquivo com dados brutos de cada requisição contendo horário e métricas de dura-

ção da requisição (opção -g do Apache Benchmark)

◦ arquivo contendo métrica da média de requisições por segundo agrupados pela du-

ração da execução em porcentagem (de 0 à 100%) (opção -e do Apache Bench-

mark).

◦ log com todos os dados da execução de cada teste pelo Apache Benchmark

5. Com os dados coletados, serão gerados gráficos automaticamente utilizando a ferra-

menta desenvolvida para realizar os benchmarks automatizados com auxílio do Gnu-

plot.

Todos os gráficos, exceto os de “Requisição por segundo vs Conexão concorrente”, pas-

saram por uma função “sbezier” do gnuplot com a finalidade de facilitar a visualização das

diferença obtidas em situações distintas de carga, simplificando a visualização do ganho ou da

degradação conforme a carga de conexões simultâneas aumenta.

5.3 Ferramentas

Aqui estará contido as ferramentas que serão utilizadas para mensurar e gerar as métricas

de comparação entre os diversos cenários.

Page 62: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

60

As ferramentas serão utilizadas em terminais Linux, distribuição Ubuntu Linux 11.04

LTS. Elas serão executadas e controladas por uma ferramenta auxiliar47 criada para este traba-

lho, escrita em Ruby e utilizando bibliotecas para interagir com Gnuplot.

5.3.1 Apache Benchmark

Ferramenta da Apache48, capaz de gerar requisições a um endereço específico, simulando

uma carga pré-definida de requisições com a possibilidade de se definir número de conexões

simultâneas que serão utilizadas para disparar a simulação.

Pode ser utilizada em conjunto com o Gnuplot para gerar gráficos a partir de algumas

métricas que são coletadas dos dados brutos de cada requisição (opções -e e -g, via linha de

comando).

5.3.2 Gnuplot

Ferramenta de código aberto49 utilizada para geração dos gráficos, a partir dos dados co-

letados pelo Apache Benchmark.

5.4 Cenários

Aqui estará contido em cada cenário, a relação da configuração das máquinas, serviços

instalados, configurações, etc que sejam necessários para descrever e reproduzir os testes a

serem realizados e os objetivos pretendidos com cada simulação.

5.4.1 Comparativo entre soluções de servidor multi-propósito

O objetivo desta simulação é testar os dois principais servidores multi-propósito utiliza-

dos para aplicações Ruby on Rails e avaliar o impacto da disponibilização de conteúdo estáti-

co com e sem passar pela aplicação Rails:

47 Código-fonte disponível em: https://github.com/brodock/tcc-rubyonrails

48 Disponível via pacote do Ubuntu: apache-utils

49 Disponível via pacote do Ubuntu: gnuplot

Page 63: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

61

• Apache2 + Passenger 3

• Nginx + Passenger 3

5.4.1.1 Teste 1

Objetivo: Medir capacidade de servir conteúdos estáticos de cada servidor Web, sem uti-

lizar a aplicação Rails, para descobrir qual servidor que possui melhor vazão.

Foi realizado uma bateria de simulações, acessado uma página html estática de 12KB.

Com base nos resultados do teste, conforme o Gráfico 4, é possível verificar que o Nginx

é claramente mais rápido que o Apache. Com a carga inicial ele se mostrou 15% mais rápido,

Gráfico 4: Valor médio de requisições por segundo do Apache e Nginx pela carga de cone-

xões concorrentes

Page 64: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

62

aumentando o ganho em relação ao Apache conforme o número de conexões concorrentes au-

mentava, se mostrando 50% mais rápido com 100 conexões concorrentes, 240% mais rápido

com 200 conexões concorrentes, chegando a 850% mais rápido com 500 conexões concorren-

tes.

Além da diferença em relação ao número de requisições em relação a conexões concor-

rentes, onde o Nginx se mostrou praticamente estável, na faixa dos 8000-9000, com exceção

ao caso com 100 conexões simultâneas, ele também obteve melhor rendimento em relação a

utilização de recursos computacionais da máquina, mantendo o Load em valor inferior a 1.0,

enquanto o Apache manteve o Load acima de 3.0, com mais de 100 conexões concorrentes.

Analisando os casos de baixa concorrência, temos o Nginx no Gráfico 5 com até 80% da

execução do teste, enviando os arquivos com menos de 10ms de latência, atingindo o pico de

Gráfico 5: Tempo médio de resposta das requisições pelo Nginx em baixa concorrência

Page 65: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

63

25ms para 80 conexões concorrentes.Já no caso do Apache, conforme o Gráfico 6 a barreira

dos 10ms é ultrapassada após 70% da execução das requisições, atingindo o teto de 44ms

com 80 conexões concorrentes.

Mesmo o Nginx sendo um pouco melhor num ambiente de baixa concorrência, a diferen-

ça acaba não sendo perceptível ao usuário considerando a métrica de latência. No entanto vale

recordar a diferença na quantidade de requisições que é possível atender, com essa diferença,

conforme visto anteriormente.

Analisando os casos de alta concorrência, a diferença passa a ser ainda maior entre os

dois servidores, como pode ser notado no Gráfico 7 e Gráfico 8.

No Gráfico 7, o Nginx se mostrou bastante estável durante todo o teste, mantendo a la-

tência das requisições, em mais da metade da execução, abaixo dos 50ms, considerando o

Gráfico 6: Tempo médio de resposta das requisições pelo Apache em baixa concorrência

Page 66: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

64

caso de maior concorrência, e nos demais casos próximo de 80% de todas requisições ficaram

a baixo desse limite. O teto para os casos de 400 conexões concorrentes e 500 foi de 350ms.

No Gráfico 8, o Apache também mostrou estabilidade em boa parte dos testes, com res-

posta até melhor que do Nginx em boa parte do teste porém próximo do final dele, devido a

exaustão dos recursos da máquina, o teto da execução foi muito maior, indo a 4s.

Dessa forma, conclui-se que apesar da performance inicial do Apache ser muito boa, ela

não se mantem no decorrer do seu funcionamento. A grande diferença que se viu, principal-

mente no , mostrando que a sua arquitetura não bloqueante faz uma grande diferença em situ-

ações de alta concorrência.

Gráfico 7: Tempo médio de resposta das requisições pelo Nginx em alta concorrência

Page 67: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

65

5.4.1.2 Teste 2

Objetivo: Medir capacidade de servir conteúdo estático de cada solução, com o conteúdo

sendo gerado por uma aplicação Rails simplificada, de forma a poder comparar de maneira

simplificada, o peso de disponibilização de páginas HTML, geradas por uma aplicação Rails,

em comparação com a distribuição estática de um servidor Web de multi-propósito.

Para manter este teste comparável com o anterior, essa aplicação foi composta pelo tem-

plate padrão de uma aplicação Rails, com um Controller que responde a requisição para o en-

dereço principal (Ex: http://www.example.com/) e uma ação que exibe a página estática, com

o mesmo conteúdo do teste anterior.

Observando o Gráfico 9, conseguimos notar o mesmo padrão apresentado no Gráfico 4,

onde a solução com Nginx se mostrou mais performática que a solução com com Apache,

sendo aproximadamente 7% melhor com 20 conexões concorrentes, 9% melhor com 40 cone-

xões concorrentes, 14% melhor com 60 conexões concorrentes, chegando a um ganho de 35%

em relação ao Apache com 100 conexões concorrentes.

Gráfico 8: Tempo médio de resposta das requisições pelo Apache em alta concorrência

Page 68: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

66

Vale uma observação importante aqui que, não foi possível extrair dados úteis com mais

de 100 conexões concorrentes na solução Nginx+Passenger. O problema ocorre devido ao es-

touro da fila de requisições no Passenger, que não consegue enfileirar muito mais acessos do

que são repassados para ele pelo Nginx.

Não foi encontrado na sua documentação nenhuma referência a esta limitação e nenhuma

explicação do por que ela não existe na solução com Apache.

O Nginx trata a situação, retornando um erro “502 – Bad Gateway”, que significa que ele

não obteve resposta da aplicação ao qual ele estava fazendo o “relay” da conexão.

Gráfico 9: Valor médio de requisições por segundo do Apache+Passenger e Nginx+Passenger

pela carga de conexões concorrentes

Page 69: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

67

Podemos considerar neste caso duas conclusões. A primeira é que, se a aplicação necessi-

tar de performance, pode ser adotado uma solução utilizando Nginx, com a consciência de

que será necessário ter sempre recursos computacionais em sobra, para evitar entregar uma

requisição “falha” ao usuário.

Vale lembrar que esse comportamento também oferece uma certa proteção contra possí-

veis ataques de negação de serviço, já que, ao não conseguir responder todas as requisições,

elas são simplesmente descartadas, ao contrario de tentar enfileirar todas elas até a exaustão

completa de recursos da máquina.

No entanto se a opção é por não perder uma requisição sequer, mesmo que ela seja entre-

gue um pouco mais lentamente, então podemos concluir que a opção do Apache é a mais indi-

cada.

No comparativo entre os resultados do Teste 1 com os do Teste 2, vemos pelo Gráfico 10,

que a maior diferença de performance ocorre em ambiente de baixa concorrência, onde o pro-

vimento de uma página estática pela solução do Nginx/Apache, é 18X mais rápida do que se

ele for utilizado em conjunto com uma aplicação Rails.

Considerando que a solução Passenger3 + Nginx não funcionou em alta concorrência,

comparamos apenas a performance do Apache com e sem a aplicação Rails, que nos leva a

uma diferença de apenas 4,5X mais velocidade pra solução sem o Rails.

Page 70: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

68

Gráfico 10: Comparativo de performance entre o resultado do Teste 1 e Teste 2

Page 71: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

69

5.4.2 Comparativo de escalabilidade horizontal vs. vertical com Ruby on Rails

O objetivo desta simulação é demonstrar que é possível utilizar tanto escalabilidade hori-

zontal como vertical em aplicações Ruby on Rails, e fornecer dados para auxiliar na decisão d

e qual solução utilizar para um novo projeto, pensando nos resultados que pretende-se obter.

Para ser mais fiel a situação de uma aplicação real, será feito uma simulação otimista,

onde a maior parte das requisições contarão com cache de banco de dados da aplicação, e

uma simulação pessimista, onde haverá atualização constante na base de dados enquanto

ocorre acesso as mesmas informações, limitando a efetividade do cache.

Com base nos resultados do teste anterior, o servidor de multi-propósito que será utiliza-

do para a aplicação Rails é o Apache, de forma a garantir que seja possível simular correta-

mente demandas de alta concorrência sem obter respostas inválidas pelo servidor.

Os seguintes valores de conexão concorrentes serão utilizados, para simplificar a análise

dos resultados: 25, 50, 75 e 100.

Questões de escalabilidade do banco de dados ficarão fora deste cenário.

Para o teste se aproximar de uma situação real, utilizaremos uma aplicação

5.4.2.1 Teste 1

Objetivo: Verificar como o aumento de recursos da máquina hospedeira pode gerar um

aumento na quantidade de requisições que a aplicação pode suportar.

Máquina 1: MySQL5.1

Máquina 2: Servidor Apache2 + Passenger3

Será executado bateria de testes com cada uma das configurações selecionadas no capítu-

lo 5.1 (exceto a pequena) sendo aplicadas a Máquina 2 juntamente com ajustes nos parâme-

tros de configuração do Passenger e Apache para adequar a disponibilidade ao tamanho das

máquinas virtuais.

Page 72: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

70

Durante a execução dos teste, foi possível notar um incremento na quantidade de requisi-

ções entre as máquinas com tamanho médio para grande, conforme é possível ver no Gráfico

11, porém ao aumentar para máquina de tamanho enorme, voltou a cair a quantidade de requi -

sições.

Essa incoerência nos dados se deu ao fato do hardware utilizado para realizar os testes,

não comportar a necessidade de processamento que a aplicação estava pedindo, e o simples

fato de acrescentar mais um núcleo não fez a diferença esperada.

Para avaliar corretamente este teste, seria necessário um hardware físico de maior porte.

Gráfico 11: Benchmark simulando escalabilidade vertical

Page 73: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

71

Apesar de não ter sido possível avaliar uma relação quantidade de recursos X incremento

no número de requisições, fica claro que, para aumentar essa quantidade através de escalabili -

dade vertical, é necessário um hardware consideravelmente melhor que o anterior.

5.4.2.2 Teste 2

Máquina 1: MySQL

Máquina 2: Load Balancer (Nginx)

Máquinas 3, 4: Servidor Apache2 + Passenger

Será executado uma primeiro teste sem a máquina 4, e na sequência um com a máquina

4. Pretende-se avaliar o impacto da introdução de um balanceador de carga na arquitetura, no

primeiro teste e no segundo verificar o ganho que pode ser obtido com essa arquitetura.

As máquinas 3 e 4 estarão configurados como máquinas média, enquanto o load balan-

cer será feito por uma máquina pequena.

Os testes utilizarão apenas uma carga de 50 conexões simultâneas.

Como é possível verificar no Gráfico 12, a solução com escalabilidade horizontal apre-

sentou um menor tempo de resposta das requisições, mesmo estando na mesma máquina físi-

ca, demonstrando que para aplicações em Ruby on Rails, trata-se da melhor alternativa.

Page 74: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

72

Os resultados de quantidade de requisições p/ segundo, ficaram em: 71 para um único

nodo e 111 para dois nodos, mostrando um incremento de 56% na quantidade de requisições

por segundo.

Infelizmente somente com dois nodos não é possível obter um retrato mais aprofundado

da capacidade de escalabilidade do framework, porém serve como guia para sugerir que essa

abordagem aparenta ser mais eficiente do que a escalabilidade vertical, como forma de incre-

mentar a capacidade da aplicação.

Gráfico 12: Benchmark para 1 e 2 nodos em ambiente com distribuição de cargas

Page 75: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

6 CONCLUSÃO

São diversas as inovações que o framework Ruby on Rails trouxe para o desenvolvimento

de aplicações web, mas ele ainda emperra na velocidade da linguagem. Por este motivo, suge-

re-se investir tempo de desenvolvimento em soluções relacionadas a cache, principalmente

que utilizem recursos dos servidores de multi-propósito aqui apresentados, conseguindo dessa

forma contornar algumas de suas deficiências e atingindo o objetivo de atender mais usuários.

Apesar de ser possível escalar uma aplicação, foi possível notar no desenvolvimento des-

te trabalho que algumas soluções tendem a funcionar melhor que outras, como é o caso da es-

calabilidade horizontal.

Ficou de fora desse trabalho estudos mais aprofundados envolvendo banco de dados, po-

rém sabe-se que este pode ser considerado o segundo fator de gargalo em qualquer aplicação

web que precise crescer.

Dessa forma, aplicações que não trabalhem com dados essencialmente transacionais, po-

dem explorar soluções que não se limitem a SGBDs Relacionais, aproveitando os benefícios

dos bancos de dados NoSQL de maneira dedicada ou em uma implementação híbrida, utili-

zando o melhor dos dois.

Page 76: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

REFERÊNCIAS BIBLIOGRÁFICAS

10gen. MongoDB. MongoDB, 2010. Disponível em: <http://www.mongodb.org/>. Acesso em: 14/5/2010.

Apache Fundation. The Apache Cassandra Project. The Apache Cassandra Project, 2011. Disponível em: <http://cassandra.apache.org/>. Acesso em: 6/6/2011.

CHILTON, I. Nginx and why you should be running it instead of, or at least in front of Apa-che. Ian Chilton, 2011. Disponível em: <http://www.ichilton.co.uk/blog/web/nginx-and-why-you-should-be-running-it-instead-of-or-at-least-in-front-of-apache-380.html>. Acesso em: 5/6/2011.

Citrusbyte. Who’s using Redis? – Redis. Redis, 2011. Disponível em: <http://redis.io/topics/whos-using-redis>. Acesso em: 6/6/2011.

LAI, H. Passenger and other Ruby frameworks. 赖洪礼的 blog, 2011. Disponível em: <http://izumi.plan99.net/blog/index.php/2008/03/27/passenger-and-other-ruby-frameworks/>. Acesso em: 15/2/2011.

Lighttpd. Lighttpd. lighttpd fly light, 2011. Disponível em: <http://www.lighttpd.net/>. Aces-so em: 27/5/2011.

ORTEGA, A. L. Cherokee Web Server. Cherokee Web Server, 2011. Disponível em: <http://www.cherokee-project.com/>. Acesso em: 27/5/2011.

Phusion. Performance and memory usage comparisons — Ruby Enterprise Edition. Perfor-mance and memory usage comparisons — Ruby Enterprise Edition, 2010. Disponível em: <http://www.rubyenterpriseedition.com/comparisons.html>. Acesso em: 18/6/2010.

ROCHA, J. A. M. DA. Modelo de Monografia e Trabalho de Conclusão de Curso (TCC). ,2007. Disponível em: <http://www.meiradarocha.jor.br/ news/ wp-content/ uploads/ 2007/09/ modelo_tcc-2006-10-19a.ott>. Acesso em: 9/3/2010.

SHAW, Z. A. mongrel2. mongrel2: mongre2, 2011. Disponível em: <http://mongrel2.org/home>. Acesso em: 27/5/2011.

Wikipédia. Lei de Amdahl. Lei de Amdahl, 2010a. Disponível em: <http://pt.wikipedia.org/wiki/Lei_de_Amdahl>. Acesso em: 13/4/2010.

Wikipédia. Escalabilidade. Escalabilidade, 2010b. Disponível em: <http://pt.wikipedia.org/wiki/Escalabilidade>. Acesso em: 30/3/2010.

Wikipédia. Balanceamento de carga. Balanceamento de carga, 2010c. Disponível em: <http://pt.wikipedia.org/wiki/Balanceamento_de_carga>. Acesso em: 9/4/2010.

Page 77: Ruby on Rails Escalável · 2011-07-18 · É realizado um levantamento das diversas opções de servidores, bases de dados relacio-nais e não relacionais (NoSQL) ... ções, para

75

Wikipédia. Aplicação Web. Aplicação Web, 2010d. Disponível em: <http://pt.wikipedia.org/wiki/Aplica%C3%A7%C3%A3o_Web>. Acesso em: 14/5/2010.

Wikipédia. Hypertext Transfer Protocol. Hypertext Transfer Protocol, 2010e. Disponível em: <http://pt.wikipedia.org/wiki/HTTP>. Acesso em: 14/5/2010.

Wikipédia. Servidor web. Servidor web, 2010f. Disponível em: <http://pt.wikipedia.org/wiki/Servidor_web>. Acesso em: 14/5/2010.

Wikipédia. Servidor de aplicação. Servidor de aplicação, 2010g. Disponível em: <http://pt.wikipedia.org/wiki/Servidor_de_aplica%C3%A7%C3%A3o>. Acesso em: 14/5/2010.

Wikipédia. Servidor Apache. Servidor Apache, 2010h. Disponível em: <http://pt.wikipedi-a.org/wiki/Servidor_Apache>. Acesso em: 6/7/2010.

Wikipédia. nginx. nginx, 2010i. Disponível em: <http://en.wikipedia.org/wiki/Nginx>. Aces-so em: 24/6/2011.

Wikipédia. NoSQL. NoSQL, 2010j. Disponível em: <http://pt.wikipedia.org/wiki/NoSQL>. Acesso em: 24/6/2010.

Wikipédia. WEBrick. WEBrick, 2011a. Disponível em: <http://en.wikipedia.org/wiki/WE-Brick>. Acesso em: 3/3/2011.

Wikipédia. Mongrel (web server). Mongrel (web server), 2011b. Disponível em: <http://en.wikipedia.org/wiki/Mongrel_(web_server)>. Acesso em: 3/3/2011.

Wikipédia. Mongrel2. Mongrel2, 2011c. Disponível em: <http://en.wikipedia.org/wiki/Mon-grel2>. Acesso em: 3/3/2011.

Wikipédia. SQLite. SQLite, 2011d. Disponível em: <http://pt.wikipedia.org/wiki/Sqlite>. Acesso em: 15/2/2011.

Wikipédia. MySQL. MySQL, 2011e. Disponível em: <http://pt.wikipedia.org/wiki/Mysql>. Acesso em: 15/2/2011.

Wikipédia. PostgreSQL. PostgreSQL, 2011f. Disponível em: <http://pt.wikipedia.org/wiki/Postgres>. Acesso em: 24/5/2011.

Wikipédia. Ruby (linguagem de programação). Ruby (linguagem de programação), 2011g. Disponível em: <http://pt.wikipedia.org/wiki/Ruby_(linguagem_de_programa%C3%A7%C3%A3o)>. Acesso em: 1/6/2011.

Wikipédia. YARV. YARV, 2011h. Disponível em: <http://en.wikipedia.org/wiki/YARV>. Acesso em: 1/6/2011.

Wikipédia. JRuby. JRuby, 2011i. Disponível em: <http://en.wikipedia.org/wiki/JRuby>. Acesso em: 1/6/2011.

Wikipédia. MacRuby. MacRuby, 2011j. Disponível em: <http://en.wikipedia.org/wiki/Ma-cRuby>. Acesso em: 1/6/2011.

Wikipédia. MagLev. MagLev (software), 2011k. Disponível em: <http://en.wikipedia.org/wiki/MagLev_(Ruby_interpreter)>. Acesso em: 1/6/2011.