glTail – Visualização de Log

26/12/2008 | Tags:, , , , , , , | Escrito por: Dirceu Pauka Jr.

glTail é um visualizador de logs escrito em Ruby. Os gráficos são gerados com a biblioteca ruby-opengl e a física das partículas é feita com Chipmunk, uma lib para desenvolvimento de física em games que possui ótima integração com Ruby.

Com ele é possível ter acesso a estatísticas em tempo real de vários serviços como Apache, Nginx, MySQL, Squid e aplicações Merb/Rails.

Tudo que você precisa para utilizar é instalar a gem (sudo gem install gltail) e alterar o arquivo de configuração para os dados de SSH e caminho de arquivos do seu servidor.

O amigo @evertonfraga testou a ferramenta com o log do Nginx no We heart it e mandou o vídeo pro Qik, vejam que legal que é:



Rack Cache – Fazendo cache corretamente

23/11/2008 | Tags:, , , , , , , | Escrito por: Dirceu Pauka Jr.

Então nós temos o HTTP a muito tempo e algumas coisas que foram revistas na versão 1.1 (RFC 2616) do protocolo só estão estão sendo implementadas para valer agora.

Uma parte importante do REST é a preocupação com o uso e implementação de alguns metodos HTTP esquecidos até agora.

Outra nova preocupação é sobre as implementações de cache do protocolo.
O protocolo HTTP vem com várias especificações sobre como cache pode ser feito nessa camada, porém, até agora foi uma parte esquecida tanto nas aplicações como nos clientes de HTTP.

Como várias aplicações (não pense somente em navegadores, mas também Web Services) começaram a seguir essas especificações para fazer cache local, era lógico que viriam implementações para os servidores que utilizamos hoje em dia.

Eu não sei você, mas eu já estou com Nginx + Rack a muito tempo. Rack é uma interface entre o servidor HTTP e o framework Ruby. No meu caso o framework é o Merb e o servidor é o Thin. O Nginx só dá uma de proxy reverso. E é ai que entra um grande potencial para ele. Com alguns cabeçalhos HTTP sendo trocados corretamente o Nginx consegue funcionar como servidor de cache facilmente.

Rack::Cache é um adapter para Rack (que servidores como Thin e Ebb usam e frameworks como Merb e Sinatra também). Além de usar corretamente os cabeçalhos HTTP sobre cache, o Rack::Cache age como um mecanismo de caching completo e totalmente fora da aplicação. Permitinde inclusive que o armazenamento seja feito no Memcached.

Por enquanto é necessário a inclusão manual do código na aplicação que está executando o Rack. Em breve espero que os próprios servidores ou frameworks incorporem as funcionalidades dessa gem Ruby.



Espancando um Web Server com Ruby

19/10/2008 | Tags:, , , , , , | Escrito por: Dirceu Pauka Jr.

Eu resolvi fazer alguns testes com Threads e Timeouts no Ruby hoje e para tal resolvi lidar com algo real: chamadas a APIs.

Problema

O problema todo da escalabilidade acontece por um simples motivo: uma chamada que demora para responder gera uma bola de neve no sistema. E esse problema da bola de neve se repete em várias partes do sistema todo. É isso que ocorre com as querys longas no MySQL ou upload de arquivo que trava uma instância do servidor e deixa todas próximas requisições lentas.

Por isso que é muito mais importante diminuir o tempo das querys longas no MySQL do que qualquer outra coisa. Você provavelmente consegue tirar mais tempo das querys mais longas, certo? Pense no lance de proporção, certo?

Problemas em escalar leitura em MySQL são comuns e por isso as soluções são amplamente conhecidas. Apesar de existir lock para leitura e outras características que machucam muito o trabalho de quem tem que escalar base de dados relacionais, caras como o Flickr fazem um bom uso do MySQL até hoje (sempre com ajuda de cache, lembre-se disso).

Mas e se a fonte de dados da aplicação é algo muito mais lento que um MySQL? E se a fonte de dados é digamos um WebService? Ou no pior dos casos: Web Scraping?

Um WebService ou uma API RESTfull não tem latência controlada como uma query rodando no MySQL local (ou em um cluster de) pode ter. Para começar a falar sobre WebServices eu penso logo em 200ms de latência só para atingir o servidor. E acredite, na maioria das vezes isso é pouco e de qualquer forma é o tempo de resposta que uma query comum no MySQL deve levar.

Além da lentidão você tem que pensar que a coisa toda pode não funcionar. Você pode fazer a requisição HTTP e ela não voltar. É da natureza do HTTP não retornar algumas requisições.

Agora você pensa em centenas de requisições entrando na fila a cada segundo em um sistema que busca os dados em uma API de tempo de resposta médio de 2 segundos. Esqueça a moleza do MySQL. 2 segundos aqui (no meu exemplo de API) é o tempo de resposta mínimo! Ferrou.

Eu já passei por isso. A maneira básica de lidar é cache. Você sabe. Todo mundo sabe…

Mas ainda acontece que as requisições são muito lentas! Muito! O cache não pode ser para sempre e as vezes acontecem coisas que lhe obrigam a limpar todo o cache.

Não importa quantos processos Ruby você abrir (ou quantas requisições/segundo seu Apache sirva em uma maquina de 16 bits), sua aplicação não escala e a culpa é da sua fonte de dados que para piorar é externa e você não pode fazer nada.

Solução

Eu estou planejando cortar muito processos Ruby de uma aplicação em Merb que bate 2MM req/dia com uma solução parecida com a experiência de hoje (que alias se encontra no final do post).

Por enquanto, para manter o serviço no ar a solução foi usar o que havia de melhor na infra: Nginx, Memcached e Thin. Ainda assim eu preciso de 75 instancias do Thin para que tudo funcione (lembre-se: cache não é eterno e requisições sem cache são extremamente lentas).

Como irei mudar o cenário? Quase da mesma forma como espanquei um WebServer a poucas horas com somente um processo Ruby aberto e muito menos banda do que um VPS costuma ter… “Threads”.

Usei Threads de Ruby aqui para a experiência que vou passar, mas para produção recomendo o uso de bibliotecas que irão gerenciar o trabalho. Nanite leva a carga de conhecimento em engenharia que a EngineYard possui, e apesar de não ter uma solução baseada especificamente na questão de threads pode servir para distribuir instâncias do servidor entre várias maquinas numa rede local (lógico que não é – e nem pretende ser – uma implementação do MapReduce). Ainda preciso fazer um bom teste com Nanite e conhecer soluções como NeverBlock. De qualquer forma, essas são boas soluções para o problema de escalabilidade. Pode confiar :)

Abaixo o código (experimental) que derrubou um IIS (inclusive expondo pedaços da aplicação). Ele mostra como eu usei o máximo da banda disponível para fazer tantas requisições em um servidor remoto até ele cair. Isso com somente um processo Ruby.

Em casos comuns o gargalo seria do script Ruby que faz as requisições no outro servidor, no caso desse script eu tranformei o gargalo em banda e na capacidade do outro servidor de me responder. Situação bem melhor do que gargalo na requisição em si.

Ouvi dizer que essa não é a maneira mais fácil de lidar com o problema, certamente no Ruby NeverBlock é uma solução legal. Como eu disse, preciso olhar com atenção.

Boa parte do código serve para estimar o tempo necessário para conclusão da tarefa e para exibir quanto tempo cada Thread está levando.
O ideal é achar um bom número para colocar no método join da Thread. Tente deixar esse número um pouco acima do tempo médio que o servidor remoto (ou serviço externo) responda tranquilo suas requisições sem cair no mesmo problema de bola de neve. O grande segredo do código está nesse valor e você precisa ajustar ele para sua realidade.

Notas da brincadeira:

  • Prefira utilizar Ruby 1.8.6. A documentação do 1.8.7 não está muito real. Principalmente com bibliotecas, onde enfrentei um probleminha com as classes Date e Time no 1.8.7.
  • Cuidado com comparação de Floats (principalmente se tratando de datas), Floats são números muito mais complexos do que parecem.
  • Hadoop


MerbCamp

15/10/2008 | Tags:, , , | Escrito por: Dirceu Pauka Jr.

O MerbCamp rolou em São Diego, Califórnia nos dias 11 e 12 desse mês. O pessoal da EngineYard mostrou ter feito um ótimo trabalho para o lançamento do Merb 1.0.

O foco da EngineYard está bem voltado em “fazer a coisa escalável”. E não é só no bizarro mundo da guerra de frameworks e linguagens. O Ezra apresentou um gem que cria um balanceador de carga entre vários processos Ruby, que eu não acho tão importante em si mas enxergo esse como um projeto que saiu da estrutura do Vertebra. Para quem não sabe Vertebra é o nome do projeto que rola dentro da EngineYard para criação de uma interface de aplicações para computação distribuída (cloud, já cansei de ouvir e tentei mudar um pouco :)

Abaixo uma apresentação com o que o pessoal do projeto Merb na EngineYard pensa sobre o atual estagio dele:

Merb Camp Keynote
View SlideShare presentation or Upload your own. (tags: merbcamp)

Perceberam que para mostrar que Rails é bem lento em comparação a Merb eles usaram o PHP como saco de pancada?

Voltando ao projeto do Ezra chamado de “Nanite“, prestem atenção nele! Logo de cara eu já identifiquei que ele resolve um grande problema que eu iria enfrentar futuramente em uma aplicação: Assincronicidade. Uma ótima resolução para problemas com escalabilidade é tranformar as partes mais lentas do sistema em assincronas. O Nanite serve como um auxilio para o desenvolvimento de uma aplicação que irá conter “background jobs”. O George fez um post legal sobre o tema: “Programação Assíncrona“, vale conferir!



Mudança de paradigma em webservers encaixa Nginx no mercado

7/7/2008 | Tags:, , , , , , , | Escrito por: Dirceu Pauka Jr.

A época de ouro do Apache parece ter acabado há algum tempo. Após muitos anos sendo o servidor de aplicações para Web mais usado (na realidade ainda sendo o mais usado), o market-share do Apache está em queda há algum tempo segundo o Netcraft.

Mas eu não vim aqui para enterrar o coitado do Apache, provavelmente já fizeram muito disso por aí… sem necessidade na minha opinião. Muitos problemas ainda podem ser resolvidos com ele, sem contar que é muita falta de consideração jogar pedra em quem te alimentou por todo esse tempo (mais de 10 anos) não é?

Estou aqui para falar das entrelinhas no levantamento de Junho da Netcraft. Mais precisamente quando eles expõem o seguinte: “nginx mais que dobrou em números; com um ganho de mais de 1 milhão de sites”.

Nginx

Nginx para quem não sabe é um servidor web escrito pelo russo Igor Sysoev que também pode ser usado como proxy reverso ou e-mail proxy (fique ligado no RSS para receber atualizações sobre proxy reverso).

Dentre as vantagens do engine X (pronúncia de nginx) estão:

  • estável
  • configuração simplificada
  • baixo consumo de recursos

Baixo consumo de memoria pode à primeira vista significar performance, mas nginx vai além, sendo desenvolvido para solucionar um grande problema de escalabilidade. Para isso possui um modelo de IO assíncrono e o já citado baixo consumo de memória que retornam além de performance, escalabilidade.

Trust Me / Thin

Há algum tempo atrás quando os widgets da boo-box foram para o ar eu não fazia idéia do poder do nginx. Sendo mais sincero do que deveria: ele só estava sendo usado pois era a opção que eu e o Maurício conhecíamos para colocar o nosso Merb no ar.

Logo no começo ele era um load balancer para um par de Mongrel em esquema Round-Robin, mas tão logo as requisições começaram a aumentar algo precisou ser feito.

Ezra Zygmuntowicz da EngineYard já havia enfrentado um problema com o modelo Round-Robin usado pela versão estável do nginx, então criou um patch para resolver isso com Fair queuing (ou quase isso).

A solução de Ezra foi de grande ajuda, pois o ponto mais díficil de escalar na aplicação que usei de exemplo é a ocorrencia de muitas requisições longas que ficam aguardando retorno de outras APIs, tornando Round-Robin impossível uma vez que algumas requisições poderiam cair em uma instância ocupada. Round-Robin não se importa se a instância está ocupada ou não e manda a requisição para fila da mesma forma e Fair resolve isso enviando requisições somente para instâncias desocupadas. Ponto para o nginx e sua crescente comunidade.

Mas outro problema é que uma vez que mais e mais requisições lentas vão entrando no sistema as instâncias ativas de Mongrel tendem a acabar. A solução poderia ser adicionar mais e mais instâncias até acabar com a memória ou com sobrecarregar a interface TCP/IP, uma vez que Mongrel não consegue trabalhar com Unix Sockets.

A solução então está sendo trabalhar com Thin, um ótimo webserver Ruby. Thin é uma solução alternativa ao Mongrel que merece um artigo dedicado, então o que posso dizer dele por enquanto é que suporta Unix Sockets (isso é bom) e tem um custo baixo de memória, possibilitando rodar várias instâncias diminuindo o desperdício de recursos.

Não estou muito certo quanto a possibilidade de se rodar qualquer aplicação Rails nele, mas de uma coisa eu sei: Merb + Thin + Nginx estão me deixando dormir tranquilamente. Se você ainda não conhece essas excelentes ferramentas do mundo Ruby acredite em mim, conheça.

Ps: nginx não é exclusivo do ambiente Ruby, ele é um proxy reverso que pode trabalhar com outras linguagens como PHP.

Ps 2: Phusion Passenger parece ser uma ótima opção para rodar Rails, mas mesmo suportando Rack não estou certo (fico devendo o benchmark) se haveria ganho para rodar Merb.



Thin próximo da versão 1.0

27/6/2008 | Tags:, , , , , | Escrito por: Dirceu Pauka Jr.

Ontem o desenvolvedor do Thin, Marc-André Cournoyer, lançou o que parece ser um release candidate para a primeira versão estável do seu servidor de aplicações Ruby[bb].

Batizada de “Double Margarita” a versão 0.8.2 não vem com muitas funcionalidades novas mas corrige todos problemas graves das versões anteriores.

Para quem não sabe do que se trata, Thin é um web server Ruby que utiliza o que há de melhor para processamento HTTP no mundo Ruby:

  • O Parser do Mongrel, de onde vem toda a velocidade e segurança do Mongrel
  • Event Machine, uma biblioteca de network I/O com foco em escalabilidade, performance e estabilidade.
  • Rack, a interface (API) entre web servers e frameworks Ruby

Essas características dão ao Thin o posto de “mais rápido que Mongrel com menos memoria que Mongrel”

Thin vs Mongrel: requisições/segundo
Thin vs Mongrel: uso de memoria

Veja o artigo que compara Thin e Mongrel de onde reproduzi os gráficos

Porém ainda vejo outra vantagem além da performance atual que é a possibilidade de Thin rodar em Ruby 1.9 desde sua versão 0.5.1, permitindo aos desenvolvedores do “ambiente Thin” (leia-se Merb) desenvolverem suas bibliotecas compatíveis com o YARV (a famosa maquina virtual por trás da performance do próximo Ruby estável). Coisa que Mongrel e o “ecossistema” em volta dele ainda não permite.

Para saber mais:
Página Oficial
Como começar (em ingles)



Framework leve acelera mais rápido!

4/11/2007 | Tags:, , , , | Escrito por: Dirceu Pauka Jr.

Só pra avisar: papo geek. Se você não tem vocação pra bixo programador ou Capitão de Projeto, recomendo outras leituras. Mas se você curte, então coloque a porra da bandoleira no notebook, porra!

É indiscutível o ganho de produtividade trazido por frameworks no desenvolvimento de qualquer aplicação, seja desktop ou web. Muito do sucesso no uso de algumas linguagens para aplicações de grande porte na verdade vem dos frameworks disponíveis. É assim com Java, com VB/C# (.NET), com Python (Django) e principalmente com Ruby (Ruby On Rails).

Muitas pessoas na verdade não tem conhecimento que o mais importante no Ruby on Rails não é toda sua estrutura de métodos e facilidades para fazer uma simples aplicação CRUD de forma organizada. O mais importante do Rails na verdade é a linguagem em que ele se baseia.

O que torna Rails atraente é a elegância do Ruby, sua sintaxe intuitiva, métodos com nomes “humanos” e a facilidade de manipular coleções de objetos.

Porém como Ruby on Rails na verdade é a porta de entrada de muita gente para o mundo Ruby, a farandula de programadores acaba só tendo olhos para ele, o framework Rails. O pessoal acaba querendo usar a mesma porcaria de martelo pra pregos diferentes. O Akita fala bastante disso, do povo que acha que pode usar Java pra fazer café e desentupir a pia…

Pra você entender melhor o que quero dizer, vou transformar frameworks em carros, ok?

Vamos pensar que nosso querido Ruby on Rails é uma F350. Você viu a foto, ela é luxuosa e bonita. Provavelmente consegue carregar muitos objetos em suas devidas classes, ou seja, tudo bem organizado. Legal, mas reparem na foto: ela é gigante e parece muito pesada!

Você sabe o que acontece com coisas pesadas! Elas demoram a acelerar.

Se você quer apenas dar uma volta na cidade não é a melhor coisa tirar a F350 da garagem. Imagine, todos aqueles sinais e você precisando fazer um monte de barulho pra poder sair junto com um simples Palio 1.8!

Para uma simples voltinha na cidade ou até mesmo uma viagem sem muita carga, existem excelentes outros carros. Não tente fazer igual eu já fiz: usar Rails pra um ou dois controllers igual nessa lista de tuitadas do Intercon.

Use tipo uma BMW (Merb, MVC-ActiveRecord igual o Rails mas BEM mais leve) ou talvez um chevetinho com motor de BMW (Sinatra, NÂO MVC então útil quando não precisar de base de dados).

Ainda tem os Audis da vida por ai (Camping), mas o importante não é simplesmente pegar um desses e sair usando eles pra tudo. O importante é conhecer varias soluções para saber ao certo qual encaixa melhor no problema!

É essa a moral da história, do post ou da vida: não se apegue em uma só solução!

Não custa repetir: veja o Merb, veja o Sinatra! É legal pra caçalho!


Aproveitando o mesmo post (assim não encho muito seu RSS Reader), gostaria de agradecer o Newton Calegari pela indicação no Meme que não entendi o propósito, mas mesmo assim eu passo a bola e indico o Thiago – Pe Vermelho. É isso!