• Aucun résultat trouvé

Dark Matter: Motivation and Constraints

2.2 Motivations and Constraints

Todos os nós em um cluster do eCaMid são réplicas idênticas uns dos outros, de forma a manter a aplicação que reside sobre o middleware tolerante a falhas. Todos os componentes da camada de serviços, como o Local Manager, o Global Manager e Naming Service estão presentes em todos os nós, embora sejam executados apenas nos nós que possuem essa responsabilidade. A maioria dos componentes da camada de serviços necessita armazenar dados, como a tabela de Lookuppresente no serviço de nomes. No entanto, esses dados não podem estar armazenados apenas na memória de um nó, pois em caso de falha do mesmo, o cluster perderá esses dados.

Por esse motivo, o eCaMid provê o Storage Service, uma abstração para um repositório chave-valor cujos dados armazenados são compartilhados por todos os nós de um cluster, onde cada nó acessa o Storage Service como se este fosse um componente local. Este repositório tem suporte à expiração de dados e controle de transações para garantir a atomicidade das operações realizadas. Várias estratégias de concorrência podem ser utilizadas no eCaMid, como concorrência eventual, locking otimista e locking pessimista. O Storage Service pode ser utilizado pela aplicação como um repositório de dados ou como cache de outras fontes de dados.

O Storage Service não faz uso do sistema de armazenamento chave-valor fornecido pela nuvem, uma vez que nem todos os provedores dispõem deste serviço, como é o caso das infraestruturas privadas OpenNebula e CloudStack. Ao invés disso, o Storage Service utilizado no eCaMid funciona como um cache distribuído, onde cada nó do cluster conta como uma partição deste sistema de armazenamento.

Os mecanismos de comunicação peer-to-peer utilizados pelo Storage Service são trans- parentes aos componentes do middleware, que utilizam de forma similar a um sistema de armazenamento local. Cada vez que um determinado valor é armazenado no Storage Service, esta entrada na tabela de armazenamento é replicada para outros N nós, onde N é determinado pela configuração do middleware e é igual ou menor que a quantidade de nós presentes em um Cluster. Quando um nó é adicionado ou removido, o Storage Service redistribui as entradas e valores armazenados entre os nós presentes.

3.4.2.1 Gerenciamento de ciclo de vida de objetos remotos

Objetos são a principal abstração usada pelo eCaMid. Objetos podem depender de outros objetos e cada um deles pode ser stateful ou stateless. Eles podem ser acessados localmente, no mesmo processo em que está sendo executado ou através de chamadas de método remotas.

O acesso a estes objetos, sejam locais, distribuídos, stateless ou stateful, deve ser trans- parente. Para garantir esta forma de transparência, objetos remotos precisam ser gerenciados pelo eCaMid, que controla como esses objetos são alocados, descartados ou acessados de forma consistente por todos os nós de um cluster.

A Figura 3.6 ilustra o modelo de domínio para o subsistema de gerenciamento de ciclo de vida do eCaMid.

O componente Lifecycle Manager é responsável por gerenciar o ciclo de vida dos objetos remotos do eCaMid. Para isto, são implementadas as estratégias Per-Request Instance e Client- Dependent Instance para definir de que forma o estado desses objetos será preservado. Ao utilizar um objeto remoto que usa a estratégia Per-Request Instance, um novo objeto será criado a cada requisição recebida de um cliente.

Objetos remotos que possuem estado utilizam a estratégia Client-Dependent Instance, que consiste em manter o estado do objeto enquanto o cliente mantém uma conexão ativa com o eCaMid. Uma conexão ativa é chamada de Sessão, que é identificada através de um UUID. O Lifecycle Managerutiliza o UUID para guardar um objeto que representa a sessão de um cliente

Figura 3.6: Modelo de domínio do subsistema de gerenciamento de ciclo de vida

através do Storage Service. Juntamente com o objeto de sessão, é guardado o estado de todos os objetos remotos cujo escopo está atrelado à sessão. Os objetos de sessão são armazenados no Storage Servicepelo Lifecycle Manager.

O Lifecycle Manager utiliza um mecanismo de Leasing para gerenciar a alocação de recursos de sessão. É definido um tempo de expiração (leasing) para todos os objetos de sessão armazenados. Caso este objeto de sessão não seja acessado por um tempo superior ao tempo de expiração, o Storage Service descarta o objeto de sessão, liberando os recursos que foram alocados.

A resiliência do estado dos objetos é garantida pelo Storage Service, onde cada objeto de sessão é armazenada como uma entrada na tabela chave-valor e replicado para os outros nós. Existe a garantia de que o estado de um objeto esteja disponível no Cluster desde que no máximo N-1 nós falhem abruptamente, onde N é o número de nós onde cada entrada chave-valor, sem a chance de que o Storage Service consiga sincronizar esses objetos para os demais nós.

Uma estratégia de consistência eventual é utilizada para manter o estado do objeto de sessão consistente sobre todos os demais nós. Caso o objeto seja acessado concorrentemente em múltiplos nós e seu estado seja alterado, o último valor a ser atualizado será armazenado no Storage Service. O problema de se utilizar mecanismos mais eficazes de controle de concorrência é que esses mecanismos tendem a dificultar a escalabilidade da aplicação quando existe uma grande quantidade de nós disputando os mesmos recursos. No entanto, o risco de acessar Client- Dependent Instancesinconsistentes é pequeno, visto que apenas um cliente em dado momento pode realmente acessar este objeto. Caso, o mesmo cliente faça uma atualização dos objetos em dois nós diferentes simultaneamente, a última atualização ao estado do objeto irá sobrescrever a entrada existente na tabela de armazenamento.

Por esse motivo, o eCaMid não suporta a estratégia Static Instance, visto que o nível de concorrência ao estado deste tipo de objeto poderia limitar de forma severa a escalabilidade do middleware, ou impedir que este mantivesse um estado consistente. Portanto, componentes

Figura 3.7: Componentes envolvidos na criação de objetos de sessão.

do middleware que precisam guardar estado (como Naming Service, Global Manager e Local Manager) utilizam o Storage Service diretamente.

A Figura 3.7 mostra os elementos envolvidos durante a criação de um proxy que será usado para acessar um objeto remoto. O cliente, quando deseja acessar um objeto remoto (seja este stateless ou stateful), utiliza o Session Factory para iniciar uma conexão com o eCaMid. O Session Factorysolicita a criação de uma sessão para o Naming Service, que gera um UUID, e publica uma mensagem de criação de sessão através do Cluster Event Bus. Este componente notifica o Lifecycle Manager de um nó específico do evento de criação da sessão, que por sua vez cria o objeto que representa a sessão, posteriormente o armazenando no Storage Service.

O Session Factory cria um objeto chamado SessionHandler, que representa a sessão criada pelo cliente. Este session handler é uma representação da conexão criada pelo cliente para o cluster. O Session Handler também é responsável por localizar objetos remotos e criar Proxies que representam essas instâncias. Os Proxies são usados pelo cliente para realizar chamadas remotas de método.

A Figura 3.8 ilustra os elementos envolvidos na invocação de métodos remotos. Quando o cliente invoca um método em um Proxy, este constrói uma mensagem chamada de Method Request Message. Esta mensagem é entregue ao Requestor, que insere outros cabeçalhos na mensagem, obtém o endereço de rede do nó que possui a instância do objeto e por fim envia a mensagem através de componentes de infraestrutura. O Invoker recebe uma Method Request Message, extrai o identificador da sessão e solicita a criação de um objeto remoto ao Lifecycle Manager. Caso o objeto remoto possua estado, este será criado utilizando o estado armazenado na sessão.

Figura 3.8: Componentes envolvidos em uma requisição de método remota.

O modelo de domínio inicial do eCaMid, apresentado na Figura 3.1, mostra que todos os componentes do eCaMid podem acessar objetos remotos. No entanto, apenas objetos que utilizam a estratégia Per-Request Instance podem ser referenciados por Observers e Tarefas, visto que a informação de sessão não está presente em operações assíncronas.

3.4.3

Balanceamento de Carga

Para fazer uso dos recursos do cluster de forma eficiente, o eCaMid fornece um meca- nismo de balanceamento de carga, que é adaptado ao modelo de comunicação característico dos sistemas de middleware orientados a objeto.

Durante o processo de criação de uma View, alguns dos nós do tipo worker são escolhidos para atuar como Routers, nós que encaminham requisições para outros nós, incluindo eles mesmos. Os Routers são selecionados utilizando um algoritmo de Leader Election, escolhidos a partir dos nós mais antigos do cluster, considerando algumas restrições: um nó não pode ser coordenador e router ao mesmo tempo, a não ser que só exista um único nó em todo o cluster; a quantidade de routers no cluster deve respeitar a proporção de 1 router para cada N workers, onde o valor padrão de N é igual a 5. Essas restrições são utilizadas para evitar que os nós utilizados como routers se tornem pontos únicos de falha, e não se tornem gargalos a medida que o cluster aumenta de tamanho. Em caso de adição ou indisponibilidade de um nó, um novo evento de criação da View é disparado, e o Load Balancing Service seleciona novamente os nós que exercerão o papel de routers.

Figura 3.9: Componentes envolvidos em balanceamento de carga

de carga. O componente Load Balancing Observer contém vários callbacks que verificam a chegada de eventos do framework de comunicação em grupo. O Load Balancing Service contém heurísticas para realizar a escolha dos nós que terão o papel de routers e utiliza o Storage Service para registrar essa informação. O Naming Service consulta o Load Balancing Service para obter a localização dos routers. Um subcomponente do Load Balancing Service é chamado de Load Balancing Strategye consiste em uma heurística de balanceamento de carga.

Uma parte importante do subsistema de balanceamento de carga se refere ao roteamento de requisições, que pode ser observado a partir da figura 3.10. Method Request Messages podem ser de dois tipos: Direct Request, destinadas a um objeto remoto específico; e requisições de grupo, destinadas a um grupo de objetos.

Figura 3.10: Componentes envolvidos em roteamento de requisições

O Invocation Router é um componente existente na camada de distribuição que é respon- sável por distribuir Method Request Messages para os demais nós de um cluster eCaMid. Ele recebe Method Request Messages a partir do Server Request Handler. Caso sejam requisições

diretas, este encaminha para o Invoker; caso contrário, utiliza o Load Balancing Strategy para localizar o nó a quem deve ser entregue a mensagem do tipo Group Request. Quando possui essa localização, o Invocation Router a encaminha para um nó remoto através do Group Channel. Várias implementações de Load Balancing Strategy podem existir, para diferentes algoritmos de balanceamento de carga. O eCaMid, nativamente, implementa os algoritmos Round-Robin e Random-Robin.

O processo de comunicação entre cliente e servidor através do eCaMid é similar ao processo existente em um middleware orientado a objeto tradicional. A Figura 3.11 ilustra um diagrama de sequência com todos os passos necessários para realizar a comunicação Cliente/- servidor utilizando os mecanismos de balanceamento de carga providos pelo eCaMid. Vários componentes foram omitidos do diagrama, de forma a simplificar o entendimento:

Figura 3.11: Balanceamento de carga no eCaMid

1. Cliente solicita ao Naming Service a referência a um grupo de objeto remoto (1);

2. Naming Service consulta o Load Balancing Service para obter a localização de um router, utilizando essa informação para construir um AOR e retorná-lo ao cliente (1.1);

3. Cliente recebe o AOR do Naming Service, constrói um Proxy e o utiliza-o para realizar chamadas de método remotos (2);

4. Ao receber a chamada de método, o Invocation Router consulta o Load Balancing Strategypara saber a que nó deverá encaminhar a requisição (2.1);

5. Se o nó for o mesmo que do Invocation Router, este encaminha a Method Request Messagepara o Invoker e recebe a resposta da invocação remota (2.2). Caso contrário, o Invocation Router utiliza o Group Channel como intermediário para enviar o Method Request Messageao nó destino (2.3); e

6. Invoker responde a requisição que, por sua vez, é encaminhada de volta para o Invocation Router. O Invocation Router encaminha a resposta recebida ao cliente que iniciou a chamada remota (2.3.1).

O Invocation Router pode falhar, devido a uma indisponibilidade ou desligamento do nó. Neste caso, a parte cliente do middleware deve tratar essa falha de forma transparente, refazendo uma consulta ao serviço de nomes. O processo descrito na Figura 3.12 ilustra essa situação:

Figura 3.12: Tolerância a falhas no mecanismo de balanceamento de carga.

1. O cliente realiza uma chamada remota a um nó específico. Por estar indisponível, o cliente recebe uma falha de conexão, que é tratada de forma transparente pelo cliente (1);

2. Os componentes da porção cliente do middleware realizam uma consulta ao serviço de nomes, obtendo uma nova referência para o nó em que o objeto remoto encontra-se localizado (2);

3. O cliente realiza uma requisição ao novo nó, e recebe a resposta da invocação remota (3).

É importante observar que alguns componentes foram omitidos do diagrama para simpli- ficar a explicação do processo.