Quem nunca ouviu a grande falácia de que Rails não escala? Isso foi moda durante algumas semanas enquanto o Twitter passava por problemas de escalabilidade, não necessariamente por culpa do Rails ou de Ruby, mas quem quer por lenha na fogueira não está muito preocupado com isso e quer mesmo é semear a discórdia. Muita água já passou por baixo da ponte, o Twitter agora está estável e as coisasfluem bem.
No começo deste ano o pessoal do Twitter anunciou e tornou open source o projeto Starling, criado por Blaine Cook. O Starling é o core do Twitter, ele é o servidor de filas responsável por manter em pé o Twitter. E agora como um projeto open source está disponível como gem e pode ser usado por qualquer outro projeto.
Indo direto ao ponto, o Starling é, basicamente, um servidor de filas implementado sob o protocolo do MemCache. O MemCache é um servidor de cache distribuído de altíssima performance e é largamente usado, principalmente em clusters de aplicações web.
Para usar o Starling é muito simples. Os primeiros passos são
Instalação
1) Instalar o servidor MemCache
[code]jeveaux@kamael ~ $ sudo apt-get -y install memcached[/code]
2) Instalar a gem do MemCache e
[code]jeveaux@kamael ~ $ sudo gem install memcache-client[/code]
3) Instalar a gem do Starling.
[code]jeveaux@kamael ~ $ sudo gem install starling[/code]
E pronto, isso é tudo para começarmos a usar o Starling. Se você achou a instalação simples se prepare, pois a utilização é ainda mais simples.
Usando o Starling
Se você já usou o MemCache vai sentir-se familiarizado com o Starling. A diferença é apenas na implementação do protocolo, ou seja, a utilização em código será igual a do MemCache, só que ao fazer set e get as coisas acontecerão de uma forma um pouco diferente. Por enquanto a diferença maior que percebi foi em relação do método get, que quando usado no MemCache apenas retorna um valor do cache e o mantém lá, já no caso do Starling o get retorna o valor e o remove da memória. Analisando com calma isso faz sentido, afinal não estamos mais falando de cache e sim de filas, mesmo que a implementação da fila seja feita usando cache.
Mas antes de irmos para os exemplos de código, precisamos fazer com o que o servidor de filas – duh, Starling – esteja disponível e rodando. Vamos iniciar o Starling na porta 22122 (-p) e como um daemon (-d):
[code]jeveaux@kamael ~ $ sudo starling -p 22122 -d[/code]
Isso já basta para iniciar o servidor do Starling e deixá-lo disponível para uso. Agora então vamos alimentar a fila, crie o arquivo: alimentar_fila.rb.
[code]#alimentar_fila.rb
require ‘rubygems’
require ‘memcache’
starling = MemCache.new ‘localhost:22122’
starling.set ‘fila’, ‘qualquer objeto'[/code]
Ao executar este arquivo (ruby alimenta_fila.rb) não teremos nenhum resultado visual, mas acredite, a fila chamada de‘fila’ no exemplo está recebendo objetos. Agora o trabalho será para – como dizem – consumir a fila. Vamos ao consumir_fila.rb.
[code]#consumir_fila.rb require 'rubygems' require 'memcache' starling = MemCache.new 'localhost:22122' loop { objeto_fila = starling.get 'fila' if !objeto_fila.nil? puts 'recuperado da fila:' + objeto_fila end }[/code]
E agora sim estamos prontos para colocar e remover objetos em uma fila. O exemplo para consumir os objetos ficará em loop, então você pode executá-lo numa janela do bash e em outra janela ir executando o exemplo para alimentar a fila com objetos e acompanhar o comportamento dos procedimentos de alimentar e consumir a fila. A recuperação da fila será imediata, instantânea, afinal, assim como o MemCache, o Starling está preparado para receber milhares de operações por segundo.
E é isso, o seu servidor de filas já está rodando e sendo alimentado/consumido. Agora é aplicar para o que você está precisando :D
Problemas
Há um probleminha chato com a gravação de log em disco que o Starling faz das filas. Todo o set feito gera o objeto na memória e também em disco – geralmente em /var/spool/starling/. O problema é que o get somente remove o objeto da memória e não do disco. Aparentemente isso foi feito pra ser assim mesmo e segundo o próprio Blaine Cook este arquivo de log não ficará sendo incrementado para sempre, pois, depois de um certo tamanho (o engraçado é que ele não fala esse certo tamanho) ele será rotacionado, mas por enquanto ainda não descobri este certo tamanho e o arquivo tem crescido infinitamente.
E apenas uma observação quanto ao consumir_fila.rb: Não deixe-o executando por muito tempo e nem muito menos esqueça de finalizá-lo pois como ele fica em loop infinito poderá ocupar o seu processador a toa.
Duas dicas minúsculas: em Ruby não se faz if-de-uma-linha e nem concatenação de String! ;-)
puts “recuperado da fila: #{objeto_fila}” unless objeto_fila.nil?
Valeu Kung!!! Malditos vícios de programador Java