A arquitetura Java Enterprise Edition (JEE) se baseia em componentes com recursos que gerenciam efetivamente as transações e informações de estado dos aplicativos, multiencadeamento e conjunto de recursos. Um aplicativo em JEE é mais fácil de escrever, mesmo com requisitos complexos, já que a lógica empresarial é organizada em componentes reutilizáveis e o servidor fornece os serviços subjacentes — na forma de um contêiner — para cada tipo de componente.
Pensamos que seria uma ideia inovadora dar ainda mais poder ao conceito de serviços de contêiner no JEE, incluindo suporte para algumas das ideias eficientes da computação em nuvem — ou seja, paralelismo, elasticidade, multilocação e segurança. Este artigo descreve as estratégias e padrões para estender contêineres e aplicativos de JEE com características de computação em nuvem. Inclui:
- Uma descrição de cada característica de nuvem que integramos.
- Um layout das características já existentes dos aplicativos de JEE.
- Uma descrição da nossa abordagem para estender o contêiner de JEE para a nuvem.
- Uma estratégia de design para esse tipo de migração, que inclui os conceitos de paralelismo, sincronização, armazenamento, elasticidade, multilocação e segurança.
A Figura 1 explica o que é a nuvem e os diversos modelos de implementação na nuvem.
Figura 1. Uma vista panorâmica dos modelos de serviço na nuvem e seus componentes
Na parte inferior da pilha de nuvem, encontra-se o nível de Infrastructure as a Service (IaaS). Aqui, a infraestrutura passou para a nuvem e agora a nuvem facilita a implementação de software, inclusive de aplicativos empresariais. Entretanto, a IaaS não tem um ambiente de desenvolvimento de aplicativos nem serviços de teste. Como a figura mostra, o nível superior de abstração é elasticidade, implementação automatizada e computação de utilitários.
O nível de Platform as a Service (PaaS) fornece um ambiente para criação, implementação e manutenção do software de aplicativos. O provedor de PaaS tem que oferecer os serviços básicos de ciclo de vida — como desenvolvimento, implementação e teste — serviços de blocos de construção, como gerenciamento de estado, transação e segurança, bem como serviços de gerenciamento de recursos por meio do tempo de execução.
O nível de Software as a Service (SaaS) fornece um ambiente para que o usuário final acesse um aplicativo e o use.
As características básicas de nuvem que um aplicativo precisa suportar são elasticidade e multilocação. Outras características, como aprovisionamento e automação, são suportadas por meio dos recursos de implementação do servidor de aplicativos e não têm muito impacto no código. Paralelismo, necessidades de armazenamento distribuído e melhoras na segurança atuam como características de suporte que devem ser supridas para obter elasticidade e multilocação.
Vamos examinar cada uma mais detalhadamente.
Elasticidade é a capacidade de ser escalável para mais ou para menos na infraestrutura, conforme a necessidade. Durante os períodos de pico de carga, são acrescentadas instâncias ao cluster; quando a carga diminui, o número de instâncias diminui. Isso deve ser feito dinamicamente. Essa função é habilitada por recursos do servidor de aplicativos para suportar técnicas de cluster dinâmico.
A elasticidade não é só uma solução do servidor de aplicativos — o aplicativo em si deve ter capacidade de suportar a elasticidade. Isso significa que o aplicativo deve ser projetado para lidar com os recursos que ele usa para suportar a concorrência. Ao projetar ou customizar um aplicativo para suportar a elasticidade, você também deve ter implementado paralelismo, ausência de estado e suporte para transações no seu aplicativo.
A seção de estratégia de design descreve como implementar uma elasticidade que tem todos os recursos para suportar a ausência de estado na execução e o paralelismo.
Multilocação significa que o aplicativo tem a capacidade de que uma única instância atenda vários clientes; isso significa que, se cinco clientes estão usando um serviço de gerenciamento de conteúdo, todos os cinco podem usar a mesma instância de aplicativo com a separação adequada de dados e parâmetros de execução. Para suportar a multilocação, o aplicativo precisa usar armazenamento distribuído, paralelismo, segurança e loose coupling.
Há duas abordagens para suportar a multilocação:
- Um único armazenamento físico para todos os locatários.
- Vários recursos de armazenamento físico para os locatários.
Paralelismo e suporte para transações
No conteúdo deste artigo, paralelismo é a capacidade de executar várias solicitações em paralelo ou dividir uma tarefa grande de conjunto de dados em várias subtarefas que são executadas em paralelo. Isso aproveita melhor os recursos disponíveis. O uso do paralelismo tem um impacto positivo na taxa de transferência e no desempenho. O suporte para transações assegura a confiabilidade garantindo a sincronização das mudanças de estado de qualquer recurso. Esses dois conceitos estão em extremidades opostas do espectro - se você tem mais de um, tem menos do outro.
A mescla correta de paralelismo e suporte para transações é essencial para equilibrar essas características opostas. A seção de estratégias apresenta quatro estratégias — duas para o paralelismo e duas para o suporte para transações:
- Uma abordagem síncrona e assíncrona ao paralelismo.
- Uma abordagem de conclusão de encadeamento e sincronização de chegada de dados para o suporte para transações.
A estratégia de migração descrita segue abordagens não funcionais ao paralelismo, mas há algumas que requerem alterações funcionais. Como a estrutura do Google, o MapReduce, o MR descreve uma forma de implementar o paralelismo usando a função Map que divide uma grande quantidade de dados em vários pares de chave/valor. (Consulte Recursos para ver artigos sobre o MapReduce e a nuvem.)
Loose coupling e ausência de estado
O loose coupling garante que cada chamada a um serviço seja feita por meio de uma interface padrão; isso permite que o componente chamado e o componente que chama sejam alterados sem que um afete o outro. O loose coupling é introduzido por um proxy que faz a chamada. Ausência de estado é uma propriedade do loose coupling na qual toda chamada a um serviço não depende da chamada anterior. É obtida ao gerenciar as mudanças de estado em um armazenamento persistente.
Essas duas características são complementares e tornam as chamadas de sistemas mais independentes em relação às dependências.
Armazenamento distribuído é uma forma de fazer os dados persistirem, para que o local dos dados seja irrelevante. Também significa que os mesmos dados podem ser armazenados em locais diferentes. Essa característica melhora a elasticidade e a ausência de estado, mas pode prejudicar o suporte a transações — portanto, requer um ato de equilíbrio.
Estas são quatro estratégias de armazenamento distribuído:
- Nós replicados: os dados estão disponíveis em nós diferentes e são replicados imediatamente para outros nós.
- Replicação on demand: são definidos acionadores que fazem a replicação de dados manual ou automaticamente.
- Replicação unidirecional com failover: o plano de nó de mestre para filho; durante uma falha do nó mestre, a replicação é designada para um filho específico.
- Compartilhamento de sistema de arquivos: usado quando a replicação é cara, como no caso dos recursos de sistema de arquivos.
A segurança dos aplicativos de nuvem afeta bastante certas características: multilocação, paralelismo e loose coupling introduzem outras necessidades de segurança. E se o seu aplicativo é implementado como híbrido (por exemplo, um componente de nuvem e um componente de sistema local), é necessário assegurar um recurso de conexão única para vários domínios, o que tem implicações adicionais na segurança.
Também há problemas de segurança relacionados ao armazenamento distribuído, paralelismo e transporte.
Agora que você está familiarizado com as características dos aplicativos de nuvem, vamos examinar a estrutura de um contêiner de Java EE.
Características do aplicativo de contêiner de Java EE
Os aplicativos tradicionais de JEE dependem os serviços de contêiner e do uso:
- Sessões sticky para o gerenciamento de estado da conexão
- RDBMS diretamente por meio de SQLs ou procedimentos armazenados indiretamente usando ORM
- Objetos de JMS
Eles também podem usar beans baseados em mensagens, beans de sessão e serviços da Web implementados usando a estrutura fornecida pelo contêiner. Os aplicativos recém-desenvolvidos podem usar processamento assíncrono, bem como serviços de armazenamento em cache ou serviços de JavaMail.
Vamos examinar alguns atributos e funções de aplicativos de contêiner JEE detalhadamente.
Cada pequena parte da lógica de programação pode ser abstraída em uma parte relacionada aos dados (ou à memória) e uma parte relacionada à operação (ou execução) que interagem entre si para que a operação trabalhe com os dados e os dados sejam usados pela operação. Todo o pacote do JEE — contêiner e aplicativo — pode ser abstraído da mesma forma.
A qualidade do aspecto dos dados é medida pela capacidade de garantir a confiabilidade e disponibilidade dos dados acessados, a capacidade de permitir a concorrência e a segurança dos dados em armazenamento. A qualidade do aspecto relacionado à operação é medida pela capacidade de garantir que o listener possa escutar a chegada de dados, capacidade de fazer uma chamada remota e controle de acesso e segurança do transporte.
Tabela 1. Fornecendo qualidade para o aspecto relacionado aos dados e à operação de um aplicativo de JEE
| Atributo de qualidade | Atributo de implementação | Implementação | |
|---|---|---|---|
| Dados | Confiabilidade | Transação | As transações fornecem acesso sincronizado aos dados. |
| Disponibilidade | Persistência | O tipo de persistência determina a disponibilidade dos dados. | |
| Concorrência | Gerenciamento de estado | O mecanismo de gerenciamento de estado garante a quantidade de solicitações concorrentes que podem ser processadas. | |
| Segurança | Segurança | A criptografia em armazenamento e trânsito. | |
| Operação | Comunicação assíncrona | Listener | O acionador de chamadas assíncronas. |
| Comunicação síncrona | Chamada remota | A chamada síncrona fora do processo atual. | |
| Segurança | Segurança | A verificação de controle de acesso e a segurança do transporte. |
A responsabilidade do contêiner é dupla:
- Ter um mecanismo para garantir que os atributos de qualidade dos dados e da operação sejam mantidos.
- Controlar o uso dos recursos do sistema como memória de heap, número de encadeamentos de execução, etc.
Isso leva a dois padrões distintos que você deve levar em conta — o padrão de recurso gerenciado e o padrão de tarefa gerenciada.
Um recurso gerenciado fornece um serviço relacionado aos dados e implementa gerenciamento de sessão, transação, persistência e segurança. O autor da chamada usa o diretório de nomeação para localizar o gerenciador de recursos. O gerenciador de recursos usa o conjunto de objetos fornecido pelo contêiner para gerenciar recursos de sistema. Um recurso gerenciado típico tem o padrão que você vê na Figura 2.
Figura 2. O padrão de recurso gerenciado
O contêiner ou aplicativo pode manipular o gerenciador de recursos por meio do JNDI. O gerenciador de recursos implementa o conjunto de objetos e ele obtém o recurso gerenciado que implementa persistência, gerenciamento do estado da segurança e transação.
Uma tarefa gerenciada fornece serviços relacionados à operação que implementam chamada remota, listener e segurança e usa o conjunto de encadeamentos e os serviços do diretório de nomeação fornecidos pelo contêiner. Além disso, uma tarefa gerenciada muito provavelmente resume um ou mais dos recursos gerenciados com os quais ela trabalha. O listener gerenciado é acionado pelo contêiner com base na chegada de dados — os dados podem ter a forma de tempo, mensagem ou solicitação. Também pode ser acionado pelo aplicativo.
Figura 3. O padrão de tarefa gerenciada
Cada serviço que o contêiner fornece pode ser decomposto em um dos padrões ou em uma combinação dos dois padrões. Por exemplo, o Java Message Service (JMS) tem um padrão de recurso gerenciado para o JMS Destinations e um padrão de tarefa gerenciada para o JMS MessageListener. Da mesma forma, o JDBC Connection é um padrão de recurso gerenciado.
Agora que explicamos como a função de contêiner de JEE funciona, vamos ver como estender um aplicativo de contêiner para a nuvem.
Estendendo contêineres: a abordagem básica
A abordagem para estender o contêiner para a nuvem é:
- Decompor as características da nuvem nos atributos de implementação e, em seguida,
- Melhorar o padrão de recurso gerenciado e o padrão de tarefa gerenciada com as mudanças relacionadas ao atributo de implementação.
A seção de estratégias mostra como o padrão de recurso gerenciado é estendido para o recurso de nuvem e o padrão de tarefa gerenciada é estendido para o padrão de tarefa na nuvem.
O padrão de recurso gerenciado usa as seguintes extensões para criar o padrão de recurso de nuvem (veja a Figura 4):
- CloudResource
- Isolador
- Replicador
- LockManager
- LockDataResource
- StateDataResource
Da mesma forma, o padrão de tarefa gerenciada é estendido com Proxy e StateManager para criar o padrão de tarefa na nuvem (veja a Figura 5).
Vamos tratar de alguns desses componentes.
O padrão de recurso na nuvem inclui a lista de extensões que acabou de ser mencionada. Esta é a descrição de cada componente e das interações entre eles:
CloudResource
O CloudResource estende o recurso gerenciado para incluir transações distribuídas e lógica de persistência de estado, se necessário.
StateDataResource
O StateDataResource é uma instância do CloudResource que representa uma mudança de estado referente ao recurso de nuvem em questão. A lógica de persistência de estado propriamente dita é executada de forma stateless.
Isolador
O Isolador usa um campo de controle na entrada para identificar o locatário do cliente e aplica a lógica relevante de segurança e partição para armazenar no local correto. O Isolador garante que o código do aplicativo não fique desarrumado com as estratégias de armazenamento de multilocação e assegura a aplicação da estratégia correta de multilocação. O Isolador propriamente dito é uma coleção de CloudResources.
Replicador
O Replicador só é usado se os nós replicados e as estratégias de armazenamento on demand de replicação são utilizados. O Replicador garante que os dados persistam em todos os nós replicados como uma única transação distribuída. A diferença entre o Isolador e o Replicador é que o Isolador garante que os dados vão para o armazenamento correto com base no locatário e o Replicador garante que os dados vão para todos os armazenamentos replicados para o mesmo locatário.
LockManager e LockDataResource
A funcionalidade do LockManager é bloquear dados específicos referentes a um encadeamento em um processo em todos os Replicadores. O LockManager garante a mesma visualização do status em todos os nós replicados. Isso significa que, se os dados são bloqueados para um encadeamento em um processo de servidor no servidor 1, o processo do servidor 2 verá o status como bloqueado mesmo se examinar uma réplica do armazenamento. Esse recurso só é necessário para os nós replicados e as estratégias de replicação on demand.
As mudanças gerais no padrão podem ser resumidas da seguinte forma (Figura 4):
- Agora o gerenciador de recursos fornece Isoladores que, por sua vez, fornecem um CloudResource diretamente ou um Replicator, dependendo da estratégia de armazenamento.
- Agora o recurso de nuvem suporta transações distribuídas e o gerenciamento de estado também trata a persistência de estado.
Figura 4. O padrão de recurso de nuvem agora suporta transações distribuídas
O padrão de tarefa de nuvem estende o padrão de tarefa gerenciada com as extensões Proxy e StateManager. O Proxy determina a estratégia de paralelismo e instrui o StateManager a controlar a persistência de estado para a execução.
Proxy
O Proxy é o wrapper em torno da tarefa gerenciada com lógica de pré-processo e pós-processo. A lógica de pré-processo inclui a segurança da mensagem, seguida pela formatação da entrada com base no protocolo e pela realização da tarefa. Depois da execução da tarefa, a lógica de pós-processo decide o que fazer com a saída.
StateManager
A execução de uma tarefa stateless se destina a assegurar que a entrada para a tarefa seja o estado inicial e que todas as informações relacionadas ao estado final estejam presentes na saída. Portanto, o StateManager se encarrega da entrada e da saída e de movê-las como um CloudResource.
Figura 5. O StateManager do padrão de tarefa de nuvem move a E/S como um CloudResource
A Tabela 2 mostra os detalhes de como cada característica da nuvem e a sua estratégia de design correspondente afetam os atributos de implementação de JEE e quais padrões são referidos.
Tabela 2. Características da nuvem e o seu impacto na estratégia de design e implementação
| Características da nuvem | Estratégia de design | Atributo de implementação | Padrão | Extensões de padrão |
|---|---|---|---|---|
| Ausência de estado | Ausência de estado por meio da persistência de estado | Listener, chamador remoto | Tarefa de nuvem | StateManager |
| Ausência de estado | Ausência de estado por meio da persistência de estado | Gerenciamento de estado | Recurso de nuvem | StateDataResource |
| Armazenamento distribuído | Nós replicados, replicação on demand | Persistência | Recurso de nuvem | Replicador, LockManager, LockDataResource |
| Armazenamento distribuído | Nós replicados, replicação on demand | Transação | Recurso de nuvem | CloudResource |
| Paralelismo e sincronização | Todas as estratégias | Listener, chamador remoto | Tarefa de nuvem | Proxy |
| Loose coupling | Todas as estratégias | Listener, chamador remoto | Tarefa de nuvem | Proxy |
| Multilocação | Todas as estratégias | Persistência | Recurso de nuvem | Isolador |
| Segurança | Criptografia | Persistência | Recurso de nuvem | Isolador |
| Segurança | Criptografia | Listener, chamador remoto | Tarefa de nuvem | Proxy |
Estendendo contêineres: abordagem para serviços comuns de contêiner
Modifique os serviços de contêiner já existentes para que correspondam ao recurso de nuvem e aos padrões de tarefa de nuvem e anexe-os aplicativo da forma menos invasiva possível. Em resumo, convertemos todos os serviços para um padrão de recurso de nuvem; quando o aplicativo interage com o padrão de recurso de nuvem, ele converte esse padrão para o padrão de tarefa de nuvem e está pronto para a nuvem. A lista a seguir mostra o serviço, o método original e a abordagem que usamos.
- Serviço: JDBC Database Connections
Método legado: recursos gerenciados. Abordagem: use as versões mais recentes que suportam transações distribuídas (two-phase commit), conexão compartilhável que suporta conjunto de encadeamentos e chamada stateless. Com base nas versões mais recentes que existem, a funcionalidade remanescente pode ser fornecida usando um padrão de recurso de nuvem. - Serviço: objetos de JMS
Método legado: os emissores e receptores de JMS são tarefas, e as mensagens e destinos de JMS são objetos.
Abordagem: a mesma abordagem do JDBC Database Connections. A configuração pode ser alterada para garantir que o servidor de JMS também esteja presente em todos os nós onde o cliente de JMS também estiver presente, para ajudar na elasticidade. - Serviço: objetos de cache
Método legado: atualmente suporta serviços de cache na memória ou distribuídos.
Abordagem: todos os caches devem ser convertidos para um cache distribuído para aproveitar o compartilhamento efetivo. Opcionalmente, os serviços de cache podem ser empacotados por um adaptador de recursos de nuvem. - Serviço: sessão
Método legado: a maioria os aplicativos usa sessões sticky.
Abordagem: o código pode ser alterado de forma não invasiva ao usar um filtro para todas as solicitações e permitir que o filtro crie um HttpServletRequestWrapper customizado que pode anulargetSession()para oferecê-lo como recurso de nuvem. Elimine também a sessão sticky. - Serviço: estratégias de persistência
Método legado: A persistência baseada em ORM e gerenciada pelo contêiner será benéfica.
Abordagem: A persistência gerenciada por contêiner e baseada em Object Relational Mapping não desorganiza o código do aplicativo com a característica relacional do armazenamento. Isso também possibilita a facilidade de mudança da camada de persistência para um banco de dados não relacional. O Hibernate Shards também permite armazenamento distribuído e funciona como o Replicador no padrão de recurso de nuvem. Se o aplicativo usa um DAO (data access object) com SQLs dinâmicos e procedimentos armazenados, o objeto de valor que é passado ao DAO pode ser declarado como um recurso de nuvem usando anotações. - Serviço: Variável
Método legado: o tratamento de variáveis
Abordagem: todas as variáveis públicas e variáveis estáticas, todas as entradas/saídas de arquivo e toda a gravação no log são modificadas para serem usadas como recurso de nuvem. - Serviço: chamadas de método
Método legado: o tratamento de chamadas de método.
Abordagem: todas as chamadas de método relevantes são convertidas para uma tarefa de nuvem.
Impacto nas estratégias de design
Finalmente, vamos ver como a habilitação das características de nuvem no seu aplicativo pode afetar as estratégias de design. Vamos examinar o seguinte:
- Paralelismo síncrono e assíncrono.
- Sincronização na chegada de dados e na conclusão de encadeamento.
- Nó replicado, replicação on demand, replicação unidirecional com failover e compartilhamento do sistema de arquivos no lado do armazenamento.
- Loose coupling e ausência de estado.
- Elasticidade.
- Multilocação com armazenamento único e separado.
- Segurança.
Conforme foi mencionado anteriormente, o paralelismo implica o recurso de processamento paralelo de uma tarefa, em que a tarefa é dividida em diversas subtarefas com consolidação no final. São oferecidas duas estratégias de paralelismo: síncrono e assíncrono.
Síncrono
Nessa estratégia, o autor da chamada aguarda a conclusão da execução antes de passar para a próxima tarefa.
Cada tarefa é acionada por meio de uma chamada de serviço. A tarefa aguarda o retorno do autor da chamada. O paralelismo é introduzido executando o encadeamento principal que programa encadeamentos filho para cada tarefa, para que as tarefas executem de forma concorrente enquanto cada encadeamento executa a tarefa de forma síncrona.
A estratégia síncrona é mais adequada para a agregação de dados. Quando o aplicativo precisa de informações de origens diferentes, é possível obter dados de cada origem de forma síncrona, mas cada origem pode ser obtida concorrentemente.
Assíncrono
Nessa estratégia, o autor da chamada usa mensagens para chamar uma tarefa de forma assíncrona. Quando a tarefa é concluída, a saída da tarefa é mantida em uma área de armazenamento persistente para que a próxima tarefa a pegue.
Isso é mais adequado para tarefas de orquestração. Cada tarefa de orquestração é chamada de forma assíncrona e cada uma delas chama tarefas de agregação de dados usando a estratégia síncrona.
As estratégias de sincronização garantem o suporte para transações e, portanto, a confiabilidade da tarefa. Garante que as tarefas e os dados relevantes fiquem disponíveis antes que a próxima tarefa seja processada. Há duas estratégias de sincronização: baseada na chegada dos dados e baseada na conclusão do encadeamento.
Baseada na chegada dos dados
A sincronização na chegada dos dados implica que uma tarefa seja acionada com base na chegada de dados específicos a um local específico. É particularmente importante quando a chamada assíncrona é usada, em que, para continuar, a tarefa que chama tem que procurar a saída da tarefa chamada que aparece em um local específico.
Um encadeamento faz uma busca na área dos dados e verifica se os dados chegaram. Envia uma mensagem para a tarefa a ser acionada assim que os dados chegam. O MessageListener é uma implementação da sincronização na chegada dos dados.
Baseada na conclusão do encadeamento
Na sincronização na conclusão do encadeamento, um monitor de recursos examina encadeamentos concorrentes e sincroniza a execução das tarefas enquanto acessa o recurso. Pode-se aplicar a mesma estratégia a um recurso que tem que ser compartilhado pelas instâncias por meio de uma combinação das estratégias de sincronização na chegada dos dados e na conclusão do encadeamento.
Geralmente, essa estratégia é aplicada a encadeamentos dentro de uma única JVM. No caso de recursos externos, essa abordagem é uma extensão da sincronização na chegada dos dados, em que o status do monitor é o dado e o listener leva os dados para o encadeamento que está executando na JVM atual.
Há diversos tipos de armazenamento: bancos de dados, sistemas de arquivos, dados na memória e dispositivos de persistência — como dispositivos nativos — são apenas alguns exemplos. As necessidades críticas de uma estratégia de armazenamento são: assegurar que o aplicativo de JEE tenha uma forma de criar um objeto de rede verdadeiro, um objeto cuja mudança de estado seja refletida em todas as JVMs do cluster e tenha uma forma de migrar para uma origem de dados distribuídos quando o RDBMS SQL não funcionar. Além disso, a estratégia de armazenamento é um componente importante do paralelismo e da multilocação.
Nós replicados
A estratégia de nós replicados implica que os mesmos dados estejam disponíveis em nós diferentes e sejam replicados imediatamente para outros nós. As estratégias de replicação warm e hot são aplicáveis aos bancos de dados. As outras áreas de armazenamento precisam usar a estratégia aplicada no two-phase commit.
No mínimo, há dois encadeamentos para o suporte da execução. Um encadeamento tem uma ação de salvamento/atualização, que ele chama de forma assíncrona. Esse encadeamento envia os dados por meio de conexões de soquete para outros nós e, ao receber a resposta, ele emite o commit, que atualiza de fato os nós. O encadeamento listener escuta as mudanças de outros nós e responde a elas. A conexão de soquete pode ser substituída por mensagens ou serviços baseados em HTTP.
A replicação é mais adequada para dados somente para leitura com menos atualizações. A replicação é cara. Todos os dados em cache e na memória podem ser reprojetados como um armazenamento baseado em nós replicados.
Replicação on demand
É uma variação da estratégia de replicação em que os commits regulares são para o nó atual e o código pode acionar a replicação em um ponto lógico. A replicação também pode ser acionada conforme a necessidade usando as estratégias de sincronização.
A replicação on demand ajuda no cenário em que cada nó trabalha com dados diferentes e será combinado em etapas lógicas. Um modelo de programação no estilo do MapReduce pode usar essa estratégia.
Replicação unidirecional com failover
Outra variação da replicação é a designação de um nó mestre e a replicação de todos os dados do nó mestre para os nós filho. Durante o failover, um dos filhos se torna o nó mestre e toda a replicação começa a fluir a partir desse nó. O aplicativo sempre trabalha com o nó mestre. Essa estratégia funciona em conjunto com a estratégia de compartilhamento de sistema de arquivos para projetar para alta disponibilidade.
Compartilhamento de sistema de arquivos
Normalmente é usado com recursos baseados no sistema de arquivos, cuja replicação é cara. Nesse caso, o sistema de arquivos em si se move de um nó para outro para balancear a carga. Não fornece uma opção de disponibilidade à prova de falhas, mas chega perto disso. Os sistemas de arquivos de bancos de dados relacionais podem ser manipulados dessa forma.
Loose coupling e ausência de estado
A ausência de estado é obtida ao garantir que todos os dados necessários para a chamada estejam disponíveis e não haja dependência da máquina que processou a solicitação. O loose coupling garante que a chamada seja substituível. O REST baseado em HTTP ou uma chamada de serviço da Web pode assegurar as duas coisas.
A elasticidade é obtida ao garantir a mescla correta de suporte para paralelismo e suporte para transações e — o que é mais importante — garantir que a execução seja stateless e, portanto, repetível. O estado de cada execução persiste separadamente. A mesma instância de um objeto pode ter vários encadeamentos em execução; cada encadeamento tem uma área separada para o objeto. Isso reduz a necessidade de ter vários objetos no conjunto. Alguns provedores de banco de dados já fornecem uma conexão compartilhável para se encarregar desse recurso. Isso significa que cerca de 2 a 3 conexões são suficientes para tratar 20 a 30 transações de leitura concorrentes e compartilhadas, em média.
Quanto menor a duração da transação, melhor é para a elasticidade. Faz sentido dividir uma tarefa de longa duração em várias tarefas stateless repetíveis para reduzir o tamanho da transação.
A multilocação implica que uma instância do aplicativo pode, na verdade, atender vários clientes com a separação adequada dos dados. A multilocação levanta várias questões de design, mas a questão crítica que pode ser resolvida sem refatoração do código é a do armazenamento único x armazenamento separado para diversos locatários.
Armazenamento único para vários locatários
Isso significa que há apenas um recurso de armazenamento para todos os clientes. Essa configuração tem manutenção mais fácil e é mais escalável, já que há apenas uma separação lógica e, portanto, cada elemento de dados individual pode ser criptografado por uma chave separada. O esquema e a partição fornecem a separação lógica dos dados para bancos de dados e o namespace fornece separação lógica de dados para XML.
Armazenamento separado e individual para cada locatário
Cada cliente tem o seu próprio armazenamento. Nesse caso, há separação física dos dados. Esse modelo é adequado para aplicativos em que a política determina que os dados são sensíveis. Esse armazenamento separado deve ser acessado por meio de um serviço de roteamento para impedir que a complexidade tome conta da lógica de programação.
Necessidades adicionais de segurança surgem devido ao armazenamento distribuído e à multilocação. A estratégia de segurança precisa cuidar do armazenamento, das mensagens e da segurança do transporte. Além disso, uma implementação de nuvem híbrida ou privada virtual precisaria de uma opção de conexão única para vários domínios — portanto, a federação também desempenhará um papel.
As necessidades adicionais de segurança são uma consequência das características de nuvem específicas do aplicativo — portanto, pode-se implementar isso sem afetar o restante da funcionalidade e do código.
A metodologia que descrevemos fornece estratégias e padrões de design para ajudá-lo a habilitar características de nuvem em serviços de contêiner e a migrar aplicativos para a nuvem. O padrão de recursos de nuvem e o padrão de recursos de tarefa se destinam a ser reutilizados, e nós não fazemos pressuposições em relação à estratégia que você escolherá.
Analisamos as características que tornam os aplicativos de nuvem únicos, bem como as características correspondentes dos contêineres e aplicativos de Java EE. Adaptamos os padrões de recurso gerenciado e de tarefa gerenciada aos padrões de recursos de nuvem e tarefas de nuvem para mostrar a você como estender os serviços de contêiner para que sejam usados pelos aplicativos de nuvem.
Além disso, mostramos o impacto da integração dos contêineres de JEE a um aplicativo de nuvem nas suas estratégias de design de aplicativos de nuvem.
Finalmente, gostaríamos de ressaltar que a JEE Connector Architecture (JCA) é uma das opções para implementar as extensões nos padrões de recurso gerenciado e tarefa gerenciada. A JEE Connector Architecture fornece a estrutura para definir um recurso com gerenciamento de transações, trabalho, ciclo de vida e conexão e para melhorar a arquitetura de segurança, as comunicações de entrada e o fluxo de entrada de mensagens.
Aprender
-
A tecnologia Java no developerWorks tem vários recursos sobre o uso de contêineres em Java EE.
-
Para ver uma abordagem mais funcional ao paralelismo de aplicativos, consulte
- Descubra como o MapReduce e a computação em nuvem são ideais para lidar com dados em grande quantidade em Solucione problemas de Big Data relacionados à nuvem com o MapReduce. Novembro de 2010
- Veja como o MapReduce e a virtualização melhoram o desempenho dos nós em Usando MapReduce e balanceamento de carga em nuvens. julho de 2010
-
Estas são as referências dos conceitos usados neste artigo:
- The Five Characteristics of Cloud Computing tem uma boa seção sobre elasticidade.
- Storage Multi-Tenancy for Cloud Computing é uma boa referência sobre multilocação.
- Best practices for getting Java to work for multicore processors detalha o paralelismo e o suporte para transações.
-
Nos recursos para desenvolvedores de nuvem do developerWorks, descubra e compartilhe o conhecimento e a experiência dos desenvolvedores de aplicativos e serviços que estão desenvolvendo os seus projetos de implementação de nuvem.
-
Próximas etapas: Descubra como acessar o IBM SmartCloud Enterprise.
Obter produtos e tecnologias
-
Consulteas imagens do produto disponíveis no IBM Smart Business Development and Test IBM Cloud.
Discutir
-
Participe de um grupo de computação em nuvem no developerWorks.
-
Leia todos os ótimos blogs sobre nuvem no developerWorks.
-
Participe da comunidade do developerWorks, uma rede profissional e conjunto de ferramentas comunitárias para conectar, compartilhar e colaborar.
J. Srinivas tem 16 anos de experiência no segmento de mercado e atualmente está chefiando o grupo de foco de tecnologia para a unidade de Bancos e Mercados de Capital da Infosys LTD para a Europa. Trabalhou nos fluxos de gerenciamento de projetos e arquitetura e gosta muito de processos, tecnologia e desenvolvimento de equipes motivadas. É um dos principais membros da equipe de processo agile e divulgador da computação em nuvem na Infosys.
Jayakrishnan Ramdas tem mais de 15 anos de experiência no segmento de mercado de TI, trabalhando para a Infosys LTD, um renomado fornecedor de serviços de software. Com mais de 6 anos de experiência em arquitetura, Ramdas concluiu o TOGAF (uma estrutura de arquitetura que é padrão do segmento de mercado) e também vários programas de certificação da IBM.