View Original Text

Hide Table of Contents

"I choose to code it in BASH.... I choose to code it in BASH and other things in one week, not because it is easy, but because it is HARD!!!"

#lisíadas #DevOpLife
(modesto, eu, não?)

Federação

Uma "Federação" é uma coleção de tamanho e formação arbitrária formada por Providers e Proxies.

Um Provider nada mais é que um serviço RESTful, cuja URL esteja sempre no formato /<datasource>/<entity>/<verb>.<fmt>?<query>. Por questões de praticidade, apenas encoding UTF-8 deve ser usado.

Todos os Providers da Federação precisam concordar com a semântica dos datasources, entidades e verbos. Não há a menor chance de uma Federação sobreviver sem que este pré-requisito seja plenamente satisfeito.

A glue code da Federação é o Proxy. Este serviço mantêm um registro interno de todos os Providers que dele desejam fazer parte, e passa este a receber os requests dos clientes. Por meio de um algoritmo arbitrário (no momento, um mero round-robin), um Provider capaz de satisfazer o request é escolhido, e então um Redirect é retornado ao cliente para que ele faça novamente o Request para o Provider selecionado pelo Proxy. Não é necessariamente tarefa do Proxy (apesar do nome) tomar para si a tarefa de realizar o request e rotear o resultado para o cliente - mas nada impede que este o faça (abrindo possibilidades interessantes para bridges em Intranets).

Protocolo de Filiação

Um Provider desejoso de fazer parte de uma Federação pede o seu Registro para um Proxy de sua confiança. Uma vez escolhido o Proxy, o Provider manda um POST /register.<fmt>, com a URL a ser usada para receber os requests no cabeçalho Referer do request. Por convenção, a URL é repetida no corpo da mensagem.

O Proxy ao receber a solicitação buscará sincronamente os metadados do Provider solicitante, fará críticas de compatibilidade e se aprovado aceitará o pedido com uma mensagem de Sucesso.

Na eventualidade do pedido ser negado, será retornada uma Mensagem de Fracasso.

Observar o campo error da mensagem recebida: se True, o campo error_code conterá um identificador único que descreve o evento. Uma mensagem textual estará em error_msg.

Esta confirmação do Registro é feita sincronamente, mas o anúncio de que o Provider está na lista acontece assincronamente e sem hora marcada: um Provider só será capaz de fazer parte de uma Federação caso trate corretamente à um POST /announce.<fmt>.

Ao receber um Anúncio, o Provider se compromete à se desregistrar do Proxy em caso de shutdown de seus serviços. Um Provider pode pedir seu desregistro à qualquer instante, bem como subsequentes re-registros. A única exigência é que, uma vez sabendo que não poderá aceitar requisições, o Provider faça o desregistro nos Proxies em que tenha se registrado para evitar Negação de Serviço para os clientes.

Uma vez aceito o pedido de filiação, uma outra mensagem, esta assíncrona será enviada depois de um delay arbitrário. Este é o /announce.<fmt> - em que o Proxy anuncia que está redirecionando os requests para o Provider, e solicita que deste ponto em diante o Provider se lembre de se desfiliar da Federação em caso de shutdown.

Providers Singleton

Descobriu-se com o uso de que há serviços que não podem ser distribuídos - por exemplo, um WebRadio. É impraticável para o cliente não saber para qual Provider ele está enviando um comando de "next track", já que ele quer o comando obedecido especificamente para o que ele está ouvindo.

Para resolver o problema, criou-se o conceito de Entidades singleton. Uma Entidade singleton é uma entidade que só pode ser servida por um, e apenas um Provider. A identificação de uma Entidade está amarrada ao seu Datasource (de forma que, na prática, o singleton é a tupla [dataoource, entity] - não é razoável que diferentes datasources não possam usar um símbolo para suas entidades só porque outro já o usou (não há risco de conflito, afinal).

Um Provider com serviços singleton deve informar em seus metadados quais tuplas [Datasource, Entity] são singleton listando-as no atributo singleton_entities ao invés de entities nos seus metadados. Proxies que não saibam (ou não queiram) lidar com tais entidades simplesmente ignorarão o campo (compatibilidade reversa por efeito colateral), ao passo que apenas aqueles que estejam dispostos à se meter nesta encrenca é que tratarão deste campo.

Uma vez detectada uma colisão, o Proxy idealmente retornará uma mensagem de Fracasso listando os serviços Singleton que já estiveres registrados, mas os demais poderão aceitos normalmente. É uma mensagem de cortesia para ser registrada nos logs do serviço e permitir tratamento do conflito pelos administradores - não há nada que ambos os lados possam fazer, de forma automática, para resolver este conflito mas simplesmente ignorar o problema silenciosamente não é uma opção viável.

Na prática, a presente implementação simplesmente recusa o registro inteiro e dane-se. :-)

Notar que Proxies que não saibam lidar com singleton_entities silenciosamente ignorarão o registro destas entidades.

Protocolo de Desfiliação

Um POST /unregister.<fmt>, com o endereço do Provider no Referer (e no corpo da mensagem) solicita a desfiliação imediata. Se o Provider estiver registrado, a desfiliação será efetivada no ato sem questionamentos. Se não houver registro conhecido do Provider neste Proxy, uma mensagem de Erro é retornada.

Não há anúncios sobre a desfiliação. Espera-se que o Provider não peça novamente sua desfiliação depois, mas se o fizer o pior que pode acontecer é levar uma mensagem de erro nas fuças. :-)

Recuperação Operacional

Quando um Provider cai (controladamente ou por falha irrecuperável), sugere-se que ele mantenha persistido a lista de Proxies dos quais se registrou e a recarregue em memória.

Se o tempo de recuperação for muito grande, existe a chance de um cliente ter registrado POST /complain.<fmt> ao Proxy, situação em que este pode ter optado pela desfiliação automática.

Desta forma, possivelmente é uma boa idéia pedir novamente a filiação nos Proxies desejados - o pior que pode acontecer é o Proxy avisar que você já está filiado.

Já quando um Proxy cai, não há qualquer aviso ou anúncio a ser feito para o Provider - o efeito, durante o tempo em baixa, é que o Proxy simplesmente deixa de redirecionar requests.

Sugere-se que os Proxies persistam suas listas de Providers filiados, e após o levantamento do serviço, façam novos /announce.<fmt> para seus filiados para avisá-los de que está novamente no ar e que, caso eles tenham eliminado-o de sua lista de shutdown, o incluam novamente.

Um Provider mau-humorado pode neste momento pedir sua desfiliação - caso em que o Proxy não voltará à contatá-lo até nova filiação.

Federação de facto

As presentes implementações fornecem um mecanismo federativo onde Providers ativamente se filiam à Proxies para oferecerem seus serviços. O ponto fraco desta solução é que cabe unicamente ao Provider localizar os Proxies.

Um protocolo adicional para solucionar este problema é, no momento, RiP (Research in Progress). Planeja-se que os Proxies localizem-se entre si e troquem informações sobre seus Providers - situação em que, então, estes farão /announces.<fmt> automaticamente nos Providers filiados.

Um mecanismo fail safe também é RiP - neste caso, a queda de um Proxy deve, idealmente, fazer um redirect para outro Proxy substituto. Esta solução fatalmente envolverá um Proxy Reverso em Apache ou NGINX.

Ainda está em aberto como trabalhar a desfiliação do Provider:

Implementações Alternativas

Nenhuma conhecida no momento, mas elas são encorajas e desejadas. :-)

Não há qualquer restrição sobre linguagem de programação ou hosts - enquanto os Protocolos aqui apresentados forem seguidos, tudo funciona.