Erlang: Programação Distribuída de maneira simples

Fazia tempo que estava para blogar algo sobre como é fácil fazer programação distribuída com Erlang. Derrepente, hoje, acabei perdendo o sono e eis aqui o post.

O mais simples do mundo

Pra começar, vamos ver o exemplo mais simples de computação distribuída que se pode fazer e aprender alguma coisa com ele. Ele é como um simples chat. Pois muito bem, vejamos!

Fazendo o setup

No terminal, inicie um Eshell com o seguinte comando:

$ erl -sname jose

E num outro terminal, inicie outro Eshell com:

$ erl -sname maria

Agora vá no primeiro terminal, no Eshell do José, e execute o seguinte comando:

(jose@codezone)1> register(console_jose, self()).

E no segundo terminal, no Eshell da Maria, faça o mesmo:

(maria@codezone)1> register(console_maria, self()).

Tudo bem, setup feito, hora do bate-papo!

Jogando conversa fora

“Ei José, diga oi…”

(jose@codezone)2> {console_maria, 'maria@codezone'} ! "Oi Maria, tudo bem?".

Veja o terminal da Maria. O que aconteceu? Nada? A mensagem não chegou? Chegou, chegou sim. Vejamos:

(maria@codezone)2> regs().

Na primeira coluna, procure pelo processo console_maria. Achou? Agora veja na última coluna desse processo. Que número tem aí? 1? Pois é, isso nos indica uma coisa. Ainda nesse Eshell, execute o seguinte comando:

(maria@codezone)3> flush().

Opa! E agora? Shell got “Oi Maria, tudo bem?”, certo? Taí a mensagem que a Maria recebeu do José.

Agora, que tal a Maria ser gentil com o José e responde-lo cordialmente?

(maria@codezone)4> {console_jose, 'jose@codezone'} ! "Vou bem, e voce?".

Se você quiser, pode ver o registro de processos no Eshell do José, como fez anteriormente com o da Maria. Ou pode simplesmente:

(jose@codezone)3> flush().

E receber a mensagem Shell got “Vou bem, e voce?”.

Entendendo tudo isso

Por sorte, não há muito o que explicar até aqui – já que fizemos o exemplo mais simples do mundo. Uff!

Que tal começar do começo? Vamos entender os passos de setup?

1- A primeira coisa que fizemos foi iniciar dois Eshell que, na verdade, tornaram-se dois nós do nosso cluster de runtimes Erlang.

Todas as vezes que você inicia um Eshell com a flag -sname, o que você está fazendo é criar um nó de runtime Erlang na sua rede. Na verdade, isso pode ser feito também com a flag -name.

Qual a diferença entre elas?

-sname cria o nó e dá a ele um “short name”: nome_do_no@host;
-name, pelo contrário, cria o nó dá a ele um “long name”: nome_do_no@ip_address ou nome_do_no@host.local, no caso de rede local.

Você pode perfeitamente iniciar diversos nós em uma mesma máquina, como fizemos a pouco. No entanto, você não pode duplicar os nomes dos nós, uma vez que estes são usados para identificá-los no cluster e torná-los comunicáveis uns com os outros.

“Lembrando que o nome dos nós são sempre sufixados pelo nome/ip do host, não há problema algum em ter o mesmo nome de nó em máquinas diferentes.”

Uma outra coisa interessante de aprender aqui é como os nós se comunicam. Toda comunicação entre nós é feita por um daemon chamado epmd. Este programa faz parte do sistema de runtime Erlang e tem um papel fundamental em sua arquitetura de clusters, porque sempre que “o primeiro nó” é iniciado numa máquina, automaticamente, ele também é iniciado, caso ainda não tenha sido, e passa a escutar mensagens na porta 4369 e rotea-las para o nó apropriado.

“Independente de quantos nós estejam rodando numa máquina, sempre haverá apenas uma instância do epmd rodando.”

Por fim, ainda sobre o setup dos nós do cluster, há uma outra flag que não demonstrei no exemplo acima, mas que é bem interessante e você depois pode pesquisar a respeito.

-setcookie define um “secret cookie” que serve como um tipo de token para autenticar a comunicação entre os nós do cluster. Isso quer dizer que, somente os nós iniciados com um mesmo cookie podem se comunicar. Por outro lado, sempre que um nó é iniciado sem especificar um cookie, o runtime Erlang toma a liberdade de cria um e gravar no arquivo ~/.erlang.cookie. Nestes casos, todos os nós não iniciados com um cookie compartilharão o mesmo cookie guardado nesse arquivo.

No caso do nosso exemplo ultra simples, um cookie poderia ser usado para criar uma sala de bate-papo, onde: se um nós é iniciado informando um cookie, ele entra na sala equivalente; no entanto, quando não informado, vai para uma sala genérica.

Interessante? Pois é… E esse assunto acaba puxando o da flag -hidden, que você pode aproveitar e pesquisar também.

2- A segunda coisa que fizemos no setup foi registrar um processo alvo de nossas mensagens.

Como a idéia aqui é explicar – um pouco, porque ainda há uma porção de coisas que poderiam ser faladas, mas isso deixaria esse post imenso! Dê uma olhada na documentação oficial como funciona a arquitetura de cluster de runtimes Erlang e mostrar como este provê uma maneira simples de programação distribuída, preferi não escrever um programa de chat, mas apenas usar o próprio Eshell para isso.

Com este pré-requisito em mente, o que fiz foi apenas registrar o próprio processo do Eshell – usando self(), que você entende como funciona com um nome especifico em cada nó do cluster (console_jose para um e console_maria em o outro) para fazer a troca de mensagens entre eles.

E o bate-papo, como é que rolou?

Essa é a parte mais fácil da coisa, na minha opinião. Se você já lidou com processos em Erlang, vai tirar de letra.

1- Trocamos mensagens entre os dois processos de maneira bem semelhante ao que fazemos normalmente com processos contidos num único runtime.

A única diferença aqui é que, em vez de simplesmente codarmos algo como console_jose ! “Show de bola”, codamos {console_jose, ‘jose@codezone’} ! “Show de bola”. Ou seja, além no nome do processo, informamos também em que nó do cluster ele está, tudo em uma tupla.

Um exercício legal de você fazer é o seguinte…

a. No Eshell da Maria execute:

(maria@codezone)5> console_maria ! "Show de bola".
(maria@codezone)6> flush().

b. Depois, ainda no Eshell dela, execute:

(maria@codezone)7> console_jose ! "Show de bola".

O que aconteceu? Na primeira execução, o Eshell da Maria recebeu uma mensagem, correto? Mas na segunda execução, o Eshell “crasheou”. Por quê? Porque ele não reconheceu o átomo console_jose como sendo o nome de um processo, uma vez que o processo registrado como console_jose está em outro nó do cluster. Aliás, como o Eshell da Maria crasheou, se você tentar enviar mensagens a ele novamente, como fez anteriormente e havia funcionado, ele vai crashear novamente, porque a referência ao processo que havia sido registrada tornou-se inválida.

Você precisa ficar muito atento a isso, porque quando você manda um mensagem para um processo que está em outro nó, mesmo que ele não exista, você não receberá erro – exatamente como acontece com envio de mensagens pra processos locais inexistentes.

Quer ver? Faça o seguinte teste:

(maria@codezone)8> {console_jose_123, 'jose_abc@codezone_xyz'} ! "Nao vai crashear".

E agora, o que aconteceu? Nada!

2- Outra coisa que fizemos foi usar os truques de flush() e regs(), mas esses já são bem conhecidos.

Se você costuma usar o Eshell, com certeza, já deve ter usado flush() e regs(). Caso ainda não tenha usado, aqui vai um resumo:

- flush() descarrega as mensagens contidas na caixa postal do Eshell (que como você sabe, nada mais é do que um processo Erlang qualquer);
regs() lista os processos registrados do runtime em execução.

Só o gostinho

Como disse em algum canto nesse post, ainda há bastante o que falar sobre programação distribuída com Erlang. Só pra variar, esse post foi só pra dar o gostinho. Ainda há muito mais!

Bem, quem sabe qualquer dia desses não perco o sono novamente e escrevo um pouco mais sobre o assunto. Quem sabe?

{ 3 comments to read ... please submit one more! }

  1. Olá

    Você leu o livro do Joe Armstrong, Programming Erlang? Estou tentando rodar no windows um exemplo mas não estou conseguindo.

    Att.
    Gilmara

  2. @Gilmara

    Olá! Sim, li o livro do Armstrong e o do Francesco.

    Já rodei várias coisas no Windows, funciona bem. A única coisa que não funcionou pra mim foi coisas que lidavam com CPU, porque eram especificas pra Unix-like.

{ 1 Pingbacks/Trackbacks }

  1. Erlang: system_info pode te dizer coisas legais | CØdeZØne!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>