Caelum | Ensino e Inovação - Cursos de Java, Scrum, Ruby on Rails


O cloud computing é inevitável?

Por Paulo Silveira em 28/10/09

A Caelum.com.br roda agora no cloud. Por que? Vale a pena? Temos tantos acessos assim?

Entre os exemplos clássicos do bom uso do cloud temos o sucesso do New York Times: eles conseguiram digitalizar em PDF mais de 4 terabytes de edições do jornal muito antigas (1851-1922) usando 100 máquinas e gastando apenas 240 dólares! O cloud é perfeito para situações em que você precisa de muito desempenho e recursos por um curto período de tempo.

Essa definitivamente não é a necessidade da Caelum em rodar em um cloud. Qual seria então?

Temos várias opções para você ter seu próprio cloud: através do TerraCotta, pelo VMWare ou pelo Grid Gain. Usando esses softwares você mesmo precisa prover sua infraestrutura de máquinas, o que pode ser trabalhoso. Um nível mais abstrato e encapsulado seria usar o EC2 da Amazon: ele já fornece as máquinas, facilitando muito a manutenção, e cobra por tempo de processamento (eliminando o gasto inerente ao tempo ocioso que suas máquinas poderiam ficar). No Brasil, a Locaweb foi a pioneira ao oferecer esse serviço.


cloud locaweb

Por último, temos hosts que já provêm tudo para você: a infraestrutura e o software para permitir a escalabilidade. O Google App Engine é um desses hosts.

Aqui, sim, entra a Caelum e entra também o interesse das empresas de hosting: se o cloud é mais barato para os fornecedores por compartilhar recursos ociosos, e ainda oferece altíssima escalabilidade e disponibilidade para os clientes, temos então um casamento de interesses. Essa relação ganha-ganha fortalece muito a tendência da adoção de uma arquitetura mais elástica. Os clientes também ganham uma enorme independência de hardware, terceirizando os grandes problemas que acabam acontecendo quando temos servidores dedicados: esses servidores não são à prova de bala. Para a Caelum, mesmo sem necessidade de rodar em 100 servidores, é interessante ter o poder de fazer o deploy de nossas aplicações Web sem ter de nos preocupar se “é suficiente X micros e Y de RAM para esta aplicação?”, por menor que ela seja.

O site da Caelum usava VRaptor 3 como controlador, JSP e taglibs na visualização e Hibernate para persistência. Para colocá-lo no cloud do Google App Engine, a única grande mudança que fizemos foi migrar a camada de persistência para o BigTable. Trata-se de um banco de dados não relacional proprietário, que possui uma API específica, mas também há uma implementação (não completa) de JPA para ele, o que facilita bastante a migração.

Desvantagens? O Google App Engine ainda está em beta, e já ficou fora do ar alguns momentos, em especial o serviço do DataStore (o BigTable). Há também o problema do cold start e do plugin para o Eclipse, que é um pouco lento para iniciar o servidor de testes: falaremos com detalhes sobre ambos em um outro post. Outra desvantagem é a dependência ao BigTable: como é um serviço proprietário, migrar para qualquer outro cloud vai necessitar de ajustes, mesmo que usando a JPA.

Respondendo o título do post: independente se o seu cloud é Amazon EC2, Google App Engine ou GridGain, algo é certo: ele traz vantagens tanto para os desenvolvedores quanto para o host, mostrando que a estratégia do cloud está cada vez mais solidificada.

Agradecimentos ao Pedro Matiello, Guilherme Silveira e Sérgio Lopes pela migração do site. Em breve, postaremos detalhes de como trabalhar na Google App Engine. Teremos uma palestra sobre Cloud computing no CaelumDay no Rio de Janeiro, esse 7 de novembro!

  • Share/Bookmark

Fractais e Caos em cloud computing com o Google App Engine

Por Guilherme Silveira em 03/09/09

Estudando métodos matemáticos no curso de matemática aplicada, fiz minha iniciação científica sob supervisão do professor Eduardo Colli, em um trabalho de conclusão de curso sobre sistema dinâmicos discretos, que implementei em Java. É na área de sistemas dinâmicos – em geral não lineares – que começaram a falar sobre o comportamento caótico de determinadas partículas (uma área próxima a teoria do caos). Um dos sistemas dinâmicos mais estudados é o atrator de Lorenz.

atrator de Lorenz

Aproveitando que esses algoritmos são paralelizaveis, resolvemos colocar o Google App Engine em uma prova de fogo, e tirar proveito da plataforma em nuvem para gerar os gráficos mais rapidamente, como num cluster: não só usar o Google App Engine para escalabilidade e disponibilidade, mas sim também para performance. O principal procedimento do algoritmo consiste em iterar uma mesma função na ordem de bilhões de vezes. Isto é, na versão tradicional em uma única thread, existe um ou mais loops parecidos com esse pseudo código:


for(int tempo = 0; tempo < 60*60; tempo++) {
  for(int inicial=0;inicial < 1000; inicial++) {
    x0, x1 = condicaoInicial[inicial];
    for(int iteracao = 0; iteracao <= 100000; iteracao++) {
      x0, x1 = recalcula(x0, x1);
    }
  }
}

O código acima está bem mais simples do que o código real, mas ilustra o quão lento seria a execução do mesmo. Um exemplo comum de execução deste software envolve encontrar a bacia de atração de um atrator, tarefa que demorava entre 2 a 5 minutos para o conhecido mapa de Henon.

Em nossas máquinas, um diagrama de bifurcação de Henon, como mostrado a seguir, demorava cerca de 5 minutos para ser computado:

diagrama de bifurcação do mapa de henon

Cada um desses desenhos pode parecer rodar em um período razoavelmente curto de tempo, mas uma vez que o mapa de Henon depende de 2 parâmetros, se eu desejar varrer um desses parâmetros (considerando ele o tempo) e criar um vídeo do mesmo com duração de 1 minuto e 24 frames por segundo, o tempo médio seria de 3 horas. Em situações reais, com outros atratores, chegamos a criar filmes que demoraram mais de 7 horas para serem criados.

Para tornar esse software paralelizável, a nova aplicação possui três partes: um cliente que vai iniciar o pedido, um servidor que recebe esse pedido e dispara diversas requisições para o cloud, onde cada máquina vai gerar um pouco do gráfico.

O cliente pede para o servidor as cores que deve usar para pintar uma imagem via ajax/jsonp. A aplicação do servidor foi implementada em rails, esta dispara diversas requisições em paralelo para os servidores do Google App Engine utilizando uma API de IO não blocante, similar ao NIO no Java. Já os nós do cloud rodam Java no Google App Engine, basicamente com o código do software original. Após a execução cada nó devolve os números para o servidor ruby, que vai agregando os resultados conforme eles vão sendo processados, para gerar a imagem final.

Os testes iniciais mostraram redução de até 51 vezes no tempo de execução por executar o programa em 100 requisições paralelas ao Google App Engine:

100 iterações por requisição

Requisições Tempo total (segundos) Tempo por iteração (milisegundo)
local 6 16.6
1 3 33
10 6.4 156.25
50 14 357
100 17 588
200 23.55 849

Usando o memcached, que é o cache fornecido pelas APIs do Google App Engine, temos um ganho ainda maior:


CacheFactory cacheFactory =
       CacheManager.getInstance().getCacheFactory();
cache = cacheFactory.createCache(Collections.emptyMap());
String result = (String) cache.get(script);
if (result != null) { ... }

Após essas modificações, o nosso ganho é de um desempenho 93 vezes superior por rodar a aplicação em ~100 máquinas!

Podemos ainda melhorar esses nuúmeros se tirarmos ainda mais proveito da infraestrutura que o HTTP e a rede nos fornece: proxies. Configurando adequadamente o proxy de sua empresa o conteúdo cacheado de diversas requisições não expira até a requisição seguinte ocorrer, obtendo resultados assustadoramente rápidos. Não é a toa que os gurus dos webservices RESTFul consideram o Squid uma excelente opção no lugar de um gigante ESB.

hiperboloide

Para quem se interessar, existem diversos outros exemplos de mapas 2d de sistemas dinâmicos de relativa fácil implementação.

Processos em batch e relatórios são exemplos de tarefas que costumam demorar bastante no mundo corporativo, e muitos deles poderiam ser quebrados em tarefas paralelas. Nós programadores estaremos em breve rodando muitas das nossas aplicações no cloud: não só porque é uma maneira de ter mais escalabilidade e disponibilidade, mas também porque esse tipo de infraestrutra elástica diminui muito os custos operacionais das grandes empresas de hosting. Saber tirar proveito disso vai ser papel fundamental de todo programador. Bancos de dados não relacionais e linguagens que facilitam o trabalho da programação concorrente tornam-se excelentes nesse cenário.

  • Share/Bookmark

OndeTrabalhar.com – os bastidores desse projeto Rails

Por Cauê Guerra em 05/08/09

Desde que lançamos o OndeTrabalhar.com muitas pessoas tem nos perguntado sobre quais tecnologias foram utilizadas para construí-lo, e aqui vamos falar um pouco sobre o projeto, seu ambiente e suas gems.

O OndeTrabalhar.com está implantado em um servidor rodando Passenger com Ruby Enterprise Edition, utilizando o httpd. Ainda utilizamos o plugin ExceptionNotifier, para sermos avisados por email sempre que um erro 500 ocorre, e a gem request-log-analyzer, que analiza o arquivo de log e consegue mostrar estatísticas bem interessantes sobre o uso do sistema.

Utilizamos também as bibliotecas javascript prototype e script.aculo.us, criamos muitas rake tasks para automatizar diversas tarefas e criamos algumas regex bem malucas (com a ajuda da ferramenta Rubular, que permite que testemos uma regex muito facilmente).

Abaixo, segue a lista das principais gems e suas funcionalidades:

Além deles, ainda utilizamos algumas gems para conseguirmos fazer nossos testes, que cobrem exatos 95% do nosso código, uma excelente medida:

Como todo projeto, aprendemos novos detalhes e problemas do dia a dia que enfrentamos com Rails. Adicionamos o resultado dessa experiência no nosso curso de rails, e os detalhes mais avançados estão em um novo, que será lançado em breve.

  • Share/Bookmark

Pequenos objetos imutáveis e Tiny Types

Por Jonas Abreu em 20/07/09

Uma das grandes preocupações que temos quando estamos desenvolvendo aqui na Caelum e nas nossas consultorias é como manter o código o mais expressivo possível. Expressividade está muito ligada a uma manutenabilidade maior do código, porque código mais fácil de entender costuma ter menos bugs. Uma das técnicas que usamos pra atingir esse objetivo são os Tiny Types.

Dêem uma olhada no código do seguinte método:


public Projeto criaProjeto(String nomeProjeto,
                           String descricaoProjeto) {
       // Executa a lógica de criação do projeto
}

Digamos que esse seja um factory method para criação de Projeto. Ele seria usado da seguinte forma:


new FabricaDeProjeto().criaProjeto("nome", "descrição");

Mas nada impede que esse método seja chamado dessa forma:


new FabricaDeProjeto().criaProjeto("descrição", "nome");

Notaram a diferença sutil na ordem dos parâmetros? Isso vai acontecer? Provável. Imaginem o tempo gasto com debug para corrigir esse problema? Não seria melhor aproveitarmos a tipagem explícita do Java para pegarmos esse problema em tempo de compilação? Ficaria assim:


public Projeto criaProjeto(Nome nomeProjeto,
                           Descricao descricaoProjeto) {
       // executa a lógica de criação do projeto
}

Ganhamos checagem em tempo de compilação. Mas apenas isso? Vamos olhar como esse método seria usado:


new FabricaDeProjeto()
     .criaProjeto(new Nome("nome"), new Descricao("descrição"));

O código ficou mais expressivo. Fica bem claro que estamos passando o Nome do projeto e não algo genérico. Com isso, fica muito mais difícil confundir o que passar em cada parâmetro. Estamos fazendo uso do sistema de tipos explicitos do java para evitar problemas. Além disso existem mais vantagens, embora um pouco mais sutis.

Com esse novo design do código, temos uma melhor divisão de responsabilidade. Por exemplo, não queremos permitir que o nome do projeto possua números. Como faríamos isso na primeira forma? Colocaríamos a lógica de validação dentro do método criaProjeto. Agora não precisamos fazer isso. Podemos colocar a lógica de validação dentro do objeto Nome, que é o objeto responsável por tudo relativo à Nome. Colocamos a funcionalidade no lugar onde ela deve ficar. Dividimos melhor a responsabilidade porque podemos adicionar métodos em Nome.

Mas temos um pouco mais de trabalho pra fazer isso, correto? Será que o código não vai ficar lento porque estamos criando vários objetos apenas para encapsular Strings? Não. A forma como o Garbage Colector trabalha, coletando os objetos que devem ser mantidos em memória (e não o contrário) simplesmente não vai ser afetada pela criação dos novos objetos, que possuem vida bem curta.

Podemos ir ainda mais longe. Podemos fazer com que esses pequenos objetos sejam imutáveis. Se eles forem imutáveis, teremos diversos ganhos. Por exemplo, quem estiver manipulando esses pequenos objetos não precisará se preocupar com concorrência. Para objetos imutáveis,
não faz diferença se eles estão em um ambiente concorrente ou não: são thread safe por natureza. Esse ganho é tão importante, que existem linguagens de programação onde você não pode criar “objetos” mutáveis, como Erlang. Além da thread safety, a outra principal vantagem é não termos de nos preocupar com que código de outras pessoas modifiquem nossos objetos, sofrendo efeitos colaterais por causa da invocação de um método e passagem deste objeto como parâmetro. Também não há como nossos objetos ficarem fora de um estado consistente.

Esses pequenos objetos imutáveis podem facilitar muito o desenvolvimento, prevenindo problemas e evitando que por preguiça separemos de forma errada as responsabilidades dos objetos. No começo pode parecer que estamos criando um monte de objetos a mais, mas na verdade não é bem assim. Como esses objetos pequenos possuem responsabilidades bem definidas, fica muito fácil reaproveitar. Imaginem quantos lugares precisam ter descrição? Usaremos o mesmo pequeno tipo. O gasto inicial que temos é bem recompensante conforme o tempo passa.

  • Share/Bookmark

Falando em Agile 2008: eu fui!

Por alexandre.magno em 31/10/08

O Falando em Agile 2008 deixou saudades! Foi muito bom ver profissionais experientes não só em Agile, mas no mundo de software como um todo, discutindo durante dois dias sobre a difícil arte de fazer projetos darem certo, entregando software funcionando e com valor para o cliente. Foi muito bom ver profissionais de todos os mundo juntos: Java, .NET, Delphi, PMBok, Scrum, XP, FDD…em busca de um único objetivo!

Tivemos palestras abordando assunto para todos os gostos: cases de sucesso apresentados pela Dell, Aeronáutica e Globo.com; alertas sobre as dificuldades para a implantação de Agile; modelos para contratação de projetos ágeis; Scrum em ambientes PMBok; Kanban e muito mais. Foi realmente uma overdose!

UPDATE: Veja o vídeo de algumas das palestras.

DSC_7741_50 DSC_7744_50
DSC_7675_50 DSC_7653_50

Eu poderia neste post relatar cada uma das palestras, citar pontos positivos e negativos do evento, enfim, falar em detalhes do evento. No entanto a comunidade já está fazendo isto com maestria, então cito abaixo alguns posts sobre o Falando em Agile 2008:

Vitor Hugo Germano,
Daniel Wildt
André Faria Gomes
Fabricio Sousa
Inove
André Ferreira
Danilo Bardusco,
Guilherme Chapiewski
Antonio Carlos Silveira
Philip Calçado
Flickr do Antônio Carlos
Danilo Sato

Nós da Caelum agradecemos a todos os palestrantes, que tornaram o evento muito mais especial, e as empresas que patrocinaram e apoiaram o evento: Globo.com, Yahoo! Brasil, Borland, além da Heptagon, Sea Tecnologia, Locaweb, Scrum Alliance e ThoughtWorks. Vejo vocês
no Falando em Agile 2009, e aguardem a disponbilização de algumas palestras do evento!

  • Share/Bookmark



Caelum | Ensino e Inovação
São Paulo: Rua Vergueiro, 3185, cj. 87, próximo ao Metrô Vila Mariana   |   Tel. (11) 5571-2751
Rio de Janeiro: Rua Senador Dantas, 80, cj. 307/308 - Centro   |   Tel. (21) 2220-4156 ou 2297-0033
Brasília: SCS Qd. 8 Bl. B-50, Sala 521 - Ed. Venâncio 2000   |   Tel. (61) 3039-4222