Programação distribuída
» Slides sobre
programação distribuída
Existem várias razões para escrever aplicações distribuídas. Entre elas:
O primeiro passo para criar um ambiente distribuído em Erlang é
transformar a shell num nó com capacidades de comunicação remota. A
partir desse momento é possível executar diversas operações, como por
exemplo:
Criação de nós
Para criar um nó de um ambiente distribuído em Erlang podem ser usadas as seguintes flags na linha de comando do sistema operativo (em windows substituir o comando erl por werl):
erl -name nome_do_nó
Cria um nó Erlang. O nome do nó será nome_do_nó@máquina.domínio
Exemplo:
erl -name no1
Eshell V4.7 (abort with ^G)
(no1@alvega.dei.isep.ipp.pt)1>
erl -sname nome_do_nó
À semelhança de -name cria um nó distribuído. No entanto o formato será nome_do_nó@máquina
Exemplo:
erl -sname no1
Eshell V4.7 (abort with ^G)
(no1@alvega)1>
Esta é por vezes a única forma de criar nós num ambiente sem DNS
(Domain Name Service).
Nota: Não
existirá comunicação entre os nós criados com -name e aqueles criados com -sname, uma vez que os
nomes dos
nós têm de ser únicos num sistema distribuído.
BIFs para programação distribuída
No Erlang são usadas as seguintes BIFs para programação distribuída:
As funções spawn/4 e spawn_link/4 retornam à semelhança das suas versões com 3 argumentos um Pid que pode ser usado da forma habitual. No caso de spawn_link/4, se o nó não existir é gerado um sinal EXIT. Quase todas as operações que são normalmente usadas com Pids locais também são permitidas com Pids remotos. Por exemplo, podem ser enviadas mensagens para processos remotos e podem ser estabelecidas ligações entre os processos tal como se se tratassem de processos locais.
Para enviar mensagens a processos registados num dado nó usamos a seguinte notação:
{Nome do processo, Nome do nó} ! Mensagem
Conexões entre nós
As conexões entre nós são estabelecidas na primeira vez que se usa o
nome de um nó remoto, por exemplo se for usada a função spawn/4 ou net_adm:ping(Nó). Podem ainda ser
explicitamente estabelecidas conexões entre nós, usando a função net_kernel:connect_node(Nó). No
entanto, só será necessário estabelecer conexões explicitamente se
tiver sido usada a flag -dist_auto_connect
na linha de comandos.
As conexões são, por omissão, transitivas. Se um nó A se conectar a
um nó B e este tiver uma conexão com um nó C, então A tentará
estabelecer uma conexão com o nó C. Esta característica pode ser
alterada se se usar a flag -connect_all
false na linha de comando.
Exercícios
1) Crie 2 ou mais nós na mesma máquina. Num dos nós lance um
processo que aguarda mensagens originadas por processos do(s)
restante(s) nó(s). Sempre que recebe uma mensagem
deve imprimi-la, indicando o pid e o nó do emissor e devolve uma
confirmação de recepção.
2) Crie um sistema com um nó central e 6 nós
periféricos, de acordo com a figura 1.
Um processo master do nó
central deverá criar um processo slave
em cada um dos nós periféricos e aguardar pedidos de clientes
(que podem estar em qualquer um destes 7 nós ou noutros nós que podem
ser criados na máquina).
Os clientes recebem da linha de comando uma lista de inteiros e
pedem
ao processo master que some o
seu conteúdo.
Sempre que o master recebe
um pedido de um cliente, envia a um dos slaves a lista recebida, aguarda o
valor final da soma do seu conteúdo e devolve-o ao cliente. A
distribuição de pedidos pelos slaves deve obedecer a uma política round robin.
Se um processo slave
terminar anormalmente deve ser recriado pelo master.
Se o master receber uma
mensagem stop, deve avisar
todos os slaves que devem
terminar normalmente. Após ter a confirmação de que todos os slaves terminaram, ele próprio deve
terminar.