Como você deve ter notado, o novo gem rubi do couchbase foi lançado recentemente. A versão 1.2.2 é principalmente uma versão de manutenção com várias correções de bugs, mas você ainda pode experimentar um novo recurso experimental: integração com Máquina de eventos biblioteca. Este post lhe dará uma rápida introdução sobre como começar a usar o Couchbase Server com seus aplicativos baseados no modelo assíncrono EventMachine.
A integração do EventMachine só pode ser acessada (atualmente) em sistemas do tipo UNIX (como Linux, Solaris, BSD). Como usa fibras, também requer o MRI ruby versão 1.9 ou posterior.
Configure sua sandbox
A primeira etapa é instalar a biblioteca libcouchbase, que lida com todos os detalhes de baixo nível do protocolo do Couchbase. Você pode seguir o guia guia de instalação na página oficial. Aqui, apenas replicarei as etapas necessárias para uma máquina GNU/Linux típica (estou usando o Debian instável):
-
Instalar a chave PGP do repositório:
$ wget -O- http://packages.couchbase.com/ubuntu/couchbase.key | sudo apt-key add - -
Configurar a fonte do repositório. Aqui estou usando o link para o Ubuntu 12.04, mas, em geral, isso não importa, pois usaremos o plug-in EventMachine, que foi incorporado à própria gema. Os pacotes estão em diferentes repositórios de pacotes criados usando a mesma base de código; a única diferença é a versão das bibliotecas IO (libevent, libev) incluído na versão da distribuição.
$ sudo wget -O/etc/apt/sources.list.d/couchbase.list http://packages.couchbase.com/ubuntu/couchbase-ubuntu1204.list -
Instale os cabeçalhos da libcouchbase, a biblioteca principal e os símbolos de depuração. Novamente, talvez você queira instalar ferramentas de linha de comando ou um dos back-ends de E/S, mas isso não é necessário para a tarefa em questão.
$ sudo apt-get update
$ sudo sudo apt-get install libcouchbase-dev libcouchbase2-core libcouchbase-dbgÉ isso aí.
Agora você precisa instalar Servidor CouchbaseSiga as instruções do site oficial. Após a instalação, você terá o console do administrador em execução em http://localhost:8091 e também a API REST acessível na mesma porta. Siga as etapas de configuração inicial e, por fim, você alocará um bucket com o nome "default".
-
Por fim, você precisa instalar a própria gem. É tão fácil quanto digitar isso no terminal:
$ gem install couchbase
Criação de extensões nativas. Isso pode demorar um pouco...
Instalação bem-sucedida do couchbase-1.2.2
1 gema instalada
Instalando a documentação do ri para couchbase-1.2.2...
Instalando a documentação RDoc para couchbase-1.2.2...
Criação do aplicativo
Para demonstrar a integração, vamos criar um aplicativo de bate-papo simples usando o EventMachine e adicionar o registro de todos os eventos em um bucket do Couchbase. É extremamente fácil criar um aplicativo assíncrono com o EventMachine e, para provar isso, colocarei o código-fonte completo nesta publicação (também encontrado em exemplos/chat-em dos códigos-fonte da gem).
@@clientes = []
def post_init
@username = nil
send_data("*** Qual é o seu nome?n")
final
def receive_data(data)
se @nomedeusuário
broadcast(data.strip, @username)
mais
name = data.gsub(/s+|[[]]/, '').strip[0..20]
if name.empty?
send_data("*** Qual é o seu nome?n")
mais
@username = nome
@@clients.push(self)
broadcast("#{@username} has joined")
send_data("*** Hi, #{@username}!n")
final
final
final
def unbind
@@clients.delete(self)
broadcast("#{@username} has left") if @username
final
def broadcast(message, author = nil)
prefixo = autor ? "" : "***"
@@clients.each do |client|
a menos que cliente == self
client.send_data("#{prefix} #{message}n")
final
final
final
final
EventMachine.run do
# pressione Control + C para parar
Signal.trap("INT") { EventMachine.stop }
Signal.trap("TERM") { EventMachine.stop }
EventMachine.start_server("0.0.0.0", 9999, ChatServer)
final
Esse é um servidor EventMachine típico baseado em EM::Connection. Para aqueles que não sabem o significado desses métodos redefinidos, aqui está um trecho da seção documentação oficial:
EventMachine::Connection é uma classe que é instanciada pelo loop de processamento do EventMachine sempre que uma nova conexão é criada. (As novas conexões podem ser iniciadas localmente em um servidor remoto ou aceitas localmente de um cliente remoto). Quando um objeto Connection é instanciado, ele mistura a funcionalidade contida no módulo definido pelo usuário especificado nas chamadas para connect ou start_server. Os módulos manipuladores definidos pelo usuário podem redefinir qualquer um ou todos os métodos padrão definidos aqui, bem como adicionar código adicional arbitrário que também será misturado.
O EventMachine gerencia um objeto herdado do EventMachine::Connection (e que contém o código de usuário misturado) para cada conexão de rede que estiver ativa em um determinado momento. O loop de eventos chamará automaticamente os métodos dos objetos EventMachine::Connection sempre que ocorrerem eventos específicos nas conexões correspondentes, conforme descrito abaixo.
Essa classe nunca é instanciada pelo código do usuário e não publica um método de inicialização. Os métodos de instância de EventMachine::Connection que podem ser chamados pelo loop de eventos são: #post_init, #connection_completed, #receive_data, #unbind, #ssl_verify_peer (se TLS for usado), #ssl_handshake_completed
Todos os outros métodos de instância definidos aqui são chamados apenas pelo código do usuário.
O protocolo é muito simples e orientado por linhas. Para cada conexão, o EventMachine criará uma instância do ChatServer, que primeiro perguntará o nome do novo participante e, em seguida, transmitirá todas as suas mensagens para o grupo. Você pode usar sua ferramenta favorita que permita a comunicação por meio de um protocolo de texto arbitrário, como telnet, por exemplo, ou nc. Aqui está um exemplo de sessão entre pontos de extremidade.
Tentando 127.0.0.1... ???? *** Qual é o seu nome?
Conectado ao localhost. alice
O caractere de escape é '^]'. *** Olá, Alice!
*** Qual é o seu nome? ??? *** O Bob juntou-se a nós
bob ??? olá a todos
*** Olá, Bob! Olá, Bob! Como você está?
Olá a todos ??? ^C
Olá, Bob! Como você está? ??? ~ $
*** A Alice foi embora?
^] ???
telnet> Conexão fechada. ???
~ $ ???
Agora é hora de adicionar um pouco do Couchbase. Imagine que eu gostaria de manter todas as mensagens em um banco de dados distribuído da forma mais eficiente possível. O Couchbase é a resposta :). Para isso, preciso de:
Implemente um método de registro na classe ChatServer, que deve aceitar a mensagem e um autor opcional (para eventos do sistema, ele será nulo):
Couchbase.bucket.incr("log:key", :initial => 1) do |res|
entrada = {
'time' => Time.now.utc,
'author' => author || "[system]",
'message' => mensagem
}
Couchbase.bucket.set("log:#{res.value}", entry)
final
final
Em seguida, adiciono uma chamada para log(message, author) no método de transmissão logo antes de iterar todos os clientes conectados. E envolvo EventMachine.start_server com o retorno de chamada Couchbase::Bucket#on_connect, para executar o servidor logo após o cliente ter sido conectado. A execução do loop resultante terá a seguinte aparência:
# pressione Control + C para parar
Signal.trap("INT") { EventMachine.stop }
Signal.trap("TERM") { EventMachine.stop }
Couchbase.connection_options = {:async => true, :engine => :eventmachine}
Couchbase.bucket.on_connect do |res|
if res.success?
EventMachine.start_server("0.0.0.0", 9999, ChatServer)
mais
coloca "Não é possível se conectar ao servidor Couchbase: #{res.error}"
final
final
final
Por enquanto é isso! No futuro, podemos expandir esse exemplo para usar técnicas mais modernas, como em-sincronia e talvez websockets. Acompanhe este blog para obter atualizações.
Pontos de bônus
Apenas registrar pode não ser tão interessante, mas com o Couchbase Server você pode realizar análises simples com consultas de visualização usando a maravilha do Map-Reduce incremental do Couchbase. Por exemplo, aqui está a função Map para obter todas as entradas em ordem cronológica.
Se (doc.message) {
Se (doc.author == "[system]" && doc.time) {
emit(new Date(doc.time), "*** " + doc.message);
} else {
emit(new Date(doc.time), " " + doc.message);
}
}
}
E a saída JSON.
{"id": "log:1″, "key": "2013-02-11T19:08:05.000Z", "value": "*** alice has joined"},
{"id": "log:2″, "key": "2013-02-11T19:08:18.000Z", "value": "*** bob has joined"},
{“id”:”log:3″,”key”:”2013-02-11T19:08:38.000Z”,”value”:” hi everyone”},
{"id": "log:4″, "key": "2013-02-11T19:08:48.000Z", "value":" hello, bob! how are you?"},
{"id": "log:5″, "key": "2013-02-11T19:08:58.000Z", "value": "*** alice has left"},
{"id": "log:6″, "key": "2013-02-11T19:09:01.000Z", "value": "*** bob has left"}
]}
Ok, isso é realmente tudo por enquanto. Aproveite esse novo recurso experimental. Ele terá suporte total em uma versão futura. Se você tiver algum problema, registre um problema na seção Rastreador de problemas do projeto RCBC. Correções e contribuições também são sempre bem-vindas e o código-fonte é aberto sob a licença Apache 2.0. Você encontrará o fontes no github.