Diego Liberalquino Soares Lima ECAMID: UM MIDDLEWARE PARA NUVEM COMPUTACIONAL COM SUPORTE À ELASTICIDADE Dissertação de Mestrado Universidade Federal de Pernambuco [email protected] www.cin.ufpe.br/~posgraduacao RECIFE 2014 Universidade Federal de Pernambuco Centro de Informática Pós-graduação em Ciência da Computação Diego Liberalquino Soares Lima ECAMID: UM MIDDLEWARE PARA NUVEM COMPUTACIONAL COM SUPORTE À ELASTICIDADE Trabalho apresentado ao Programa de Pós-graduação em Ciência da Computação do Centro de Informática da Universidade Federal de Pernambuco como requisito parcial para obtenção do grau de Mestre em Ciência da Computação. Orientador: Nelson Souto Rosa RECIFE 2014 Catalogação na fonte Bibliotecária Jane Souto Maior, CRB4-571 L732e Lima, Diego Liberalquino Soares ECAMID: um middleware para nuvem computacional com suporte à elasticidade. / Diego Liberalquino Soares Lima. – Recife: O Autor, 2014. 98 f.: il., fig., tab. Orientador: Nelson Souto Rosa. Dissertação (Mestrado) – Universidade Pernambuco. CIn, Ciência da Computação, 2014. Inclui referências. Federal 1. Sistemas distribuídos. 2. Computação em nuvem. 3. Middleware. I. Lima, Diego Liberalquino Soares (orientador). II. Título. 004.36 CDD (23. ed.) UFPE- MEI 2014-190 de Dissertação de Mestrado apresentada por Diego Liberalquino Soares Lima ao programa de Pós-Graduação em Ciência da Computação do Centro de Informática da Universidade Federal de Pernambuco, sob o título eCaMid: Um Middleware para Nuvem Computacional com Suporte à Elasticidade, orientada pelo Prof. Nelson Souto Rosa e aprovada pela banca examinadora formada pelos professores: ———————————————————————– Prof. Adilson Barbosa Lopes Departamento de Informática e Matemática Aplicada/UFRN ———————————————————————– Prof. Kiev Santos da Gama Centro de Informática/UFPE ———————————————————————– Prof. Nelson Souto Rosa Centro de Informática/UFPE Visto e permitida a impressão, Recife, 13 de agosto de 2014 ———————————————————————– Profa. Edna Natividade da Silva Barros Coordenadora da Pós-Graduação em Ciência da Computação do Centro de Informática da Universidade Federal de Pernambuco. Dedico este trabalho aos meus pais, Alexandre e Carmem, e à minha futura esposa, Pollyana, por todo apoio que me foi dado nesta jornada repleta de obstáculos. Agradecimentos Gostaria de agradecer primeiramente aos meus pais, Carmem e Alexandre, por sempre estarem do meu lado ao longo deste mestrado, aconselhando-me nos momentos de dúvida, incentivando-me nos momentos de angústia e colaborando em todas as atividades cotidianas. Sem o apoio de vocês, jamais teria conseguido iniciar o mestrado, tão pouco manter-se nele face a todas as adversidades encontradas. Agradeço também à minha noiva Pollyana, por toda companhia e paciência nestes dois anos. Ambos estivemos fazendo nossos mestrados neste tempo e compartilhamos os mesmos momentos de estresse e sacrifício pessoal. Tivemos ainda que nos manter unidos frente às barreiras de um relacionamento à distância, fruto de nossas escolhas profissionais. Gostaria de agradecer também a pessoas com quem convivi na minha vida profissional nestes anos, e que demonstraram toda sua compreensão nesta jornada acadêmica. Por isso agradeço a Juliano Rabelo e Saulo Cadete da Document Solutions; Rodolfo Max, José Neto, Alan, Tony, Thiago, Eduardo e Felipe, da Petroquímica Suape; Jefferson, Frederico, Janisson, Anderson, Helder, Jairo e Cícero da Dataprev. Além destes quero agradecer a todos os amigos que mantiveram apoio, mesmo com a minha ausência dos círculos sociais nestes últimos anos, muitos desses que também estavam enfrentando as dificuldades de um mestrado. Finalmente, agradeço a Tércio Morais e Nelson Rosa pela parceria nos projetos pesquisas de middleware e nuvem que estivemos realizando neste período de mestrado. A distributed system is one in which the failure of a computer you didn’t even know existed can render your own computer unusable. —LESLIE LAMPORT Resumo Computação em nuvem fornece aplicações, plataformas e servidores virtuais como serviço, e permite que consumidores paguem pela utilização destes serviços sem que eles precisem ser adquiridos. Um dos grandes benefícios da computação em nuvem é a elasticidade, uma vez que consumidores podem requisitar mais recursos sob demanda e liberá-los quando não são mais necessários. Aplicações distribuídas desenvolvidas em nuvem devem levar em conta a presença da elasticidade para implementar sua arquitetura e serviços. No entanto, o uso efetivo da elasticidade por parte das aplicações pode ser complexo e ocasionar vários erros. Utilizando um middleware orientado a objeto existente (CaMid - Cloud-Aware Middleware), este trabalho apresenta o projeto e a implementação dos mecanismos básicos para suporte à elasticidade, tais como: replicação, coordenação de tarefas, compartilhamento de estado e balanceamento de carga. Estes mecanismos foram incorporados ao CaMid e visam maximizar a utilização dos recursos de nuvem à medida que estes são adicionados à infraestrutura da aplicação e mantê-los em funcionamento quando estes recursos são descartados. Para avaliar os mecanismos desenvolvidos, foi realizada uma avaliação experimental para identificar o impacto dos mesmos na execução das aplicações. Foi possível verificar que o CaMid conseguiu utilizar os recursos de nuvem com eficiência a um custo do overhead causado pela coordenação dos vários processos distribuídos. Palavras-chave: Sistemas Distribuídos. Computação em Nuvem. Middleware. Elasticidade. Abstract Cloud computing offers applications, platforms and virtual servers as a service, and allows consumers to pay by the use of these services, without requiring their acquisition. One of the greatest benefits of cloud computing is elasticity, since consumers may request more resources on demand and release them when they are no longer needed. Distributed applications developed by the cloud must take in account the presence of elasticity for implementing its architecture and services. However, the effective use of elasticity by the applications may prove complex and error prone. By the use of an existing object oriented middleware (CaMid - CloudAware Middleware), this work presents the project and implementation of the basic mechanisms for supporting elasticity, namely: replication, task coordination, state sharing and load balancing. These mechanisms have been incorporated to CaMid and aim to maximize cloud resources utilization while new resources are being added to application infrastructure, or keep working when the cloud resources are being discarded. In order to evaluate the developed mechanisms, an experimental evaluation has been done to identify the impact of these mechanisms during applcation execution. It was possible to verify that CaMid was able to use cloud resources with efficiency at the overhead cost caused by the coordination of the many distributed processes. Keywords: Distributed Systems. Cloud Computing. Middleware. Elasticity. Lista de Figuras 2.1 2.2 Arquitetura dos serviços de nuvem oferecidos pela Google (JIN et al., 2010) . . Relacionamento entre modelos de computação em nuvem (RIMAL; CHOI; LUMB, 2010) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 Arquitetura Genérica de Middleware . . . . . . . . . . . . . . . . . . . . . . . 2.4 Arquitetura de aplicação multi-camadas . . . . . . . . . . . . . . . . . . . . . 2.5 Invocação de método remoto em um middleware orientado a objetos . . . . . . 2.6 Relacionamento entre padrões de projeto para serviços comuns de um middleware Distributed Object Computing Middleware (DOC) . . . . . . . . . . . 2.7 Arquitetura em camadas do Cloud-Aware Middleware (CaMid), em uma pilha de serviços de nuvem (MORAIS; LIBERALQUINO; ROSA, 2013) . . . . . . 2.8 Arquitetura dos serviços de gerenciamento do CaMid . . . . . . . . . . . . . . 2.9 Interação do Local Manager com demais camadas do CaMid (MORAIS; LIBERALQUINO; ROSA, 2013) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.10 Interação do Global Manager com demais camadas do CaMid (MORAIS; LIBERALQUINO; ROSA, 2013) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 Elementos básicos do modelo de domínio do Elastic Cloud-Aware Middleware (eCaMid) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Visão geral dos componentes do eCaMid. Os elementos de cor branca representam componentes, os de cor cinza representam serviços, enquanto o elemento preto representa um framework. Os elementos em tracejado são oriundos da arquitetura do CaMid, enquantos os elementos em linha contínua foram adicionados ao eCaMid. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Estilos de comunicação um-para-um e um-para-muitos . . . . . . . . . . . . . Modelo de domínio do subsistema de publish-subscribe . . . . . . . . . . . . . Modelo de domínio do subsistema de escalonamento de tarefas . . . . . . . . . Modelo de domínio do subsistema de gerenciamento de ciclo de vida . . . . . . Componentes envolvidos na criação de objetos de sessão. . . . . . . . . . . . . Componentes envolvidos em uma requisição de método remota. . . . . . . . . Componentes envolvidos em balanceamento de carga . . . . . . . . . . . . . . Componentes envolvidos em roteamento de requisições . . . . . . . . . . . . . Balanceamento de carga no eCaMid . . . . . . . . . . . . . . . . . . . . . . . Tolerância a falhas no mecanismo de balanceamento de carga. . . . . . . . . . Diagrama de implantação para nós do eCaMid . . . . . . . . . . . . . . . . . . 23 27 31 32 33 38 42 43 44 45 50 51 53 54 55 57 58 59 60 60 61 62 64 4.1 4.2 4.3 Gráficos de barra para comparação de tempo de resposta médio entre todos os grupos de experimentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 Gráficos de barra para comparação de vazão entre todos os grupos de experimentos 78 Tempo de resposta vs tempo do experimento para comparação entre os grupos de experimentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 Lista de Tabelas 2.1 2.2 4.1 4.2 4.3 4.4 4.5 4.6 Relações entre classes de Remote Objectse mecanismos de gerenciamento de recursos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Cenários possíveis para falha de um nó e o impacto causado (WILDER, 2012) . Tempo de resposta e vazão para o grupo de experimentos Direct-Stateless . . . Tempo de resposta e vazão para o grupo de experimentos Direct-Stateful . . . . Tempo de resposta e vazão para o grupo de experimentos Elastic-ClusteredStateless . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tempo de resposta e vazão para o grupo de experimentos Elastic-Clustered-Stateful Teste estatístico Mann-Whitney comparando os grupos de experimento ElasticClustered-Stateful e Elastic-Clustered-Stateless . . . . . . . . . . . . . . . . . Teste estatístico Mann-Whitney comparando os grupos de experimento ElasticClustered-Stateful e Elastic-Clustered-Stateful . . . . . . . . . . . . . . . . . . 35 40 71 72 73 74 76 77 Lista de Acrônimos AOR Absolute Object Reference. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .35 API Application Programming Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Amazon VPC Amazon Virtual Private Cloud . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 AWS Amazon Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 WS-BPEL Business Process Execution Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 CaMid Cloud-Aware Middleware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 CDMI Cloud Data Management Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 DDS Data Distribution Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 DHT Distributed Hash Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 DOC Distributed Object Computing Middleware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 EC2 Elastic Compute Cloud . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 eCaMid Elastic Cloud-Aware Middleware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 GAE Google App Engine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 GDS Global Data Space . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 GFADS Research Group on Foundations and Applications of Distributed Systems . . . . . 18 IaaS Infrastructure as a Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 ICME Intercloud Message Exchange Middleware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 IDS Intrusion Detection System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 JVM Java Virtual Machine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 MIS Monitoring Information Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 MOM Message Oriented Middleware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 OCCI Open Cloud Computing Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 OMG Object Modeling Group . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 OSGi Open Service Gateway initiative . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 OVF Open Virtualization Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .26 OWL Web Ontology Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 P2P Peer-to-Peer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 PaaS Platform as a Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 QoS Quality of Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 REST Representational state transfer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 RMI Remote Method Invocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 RPC Remote Procedure Call . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 SaaS Software as a Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 SAN Storage Area Network . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 SLA Service Level Agreement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 SNMP Simple Network Management Protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 SOA Service Oriented Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 UUID Universally Unique Identifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Sumário 1 2 3 Introdução 1.1 O Problema . . . . . . . 1.2 Soluções Parciais . . . . 1.3 Proposta . . . . . . . . . 1.4 Estrutura da Dissertação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Conceitos Básicos 2.1 Computação em Nuvem . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 Categorias de serviço de nuvem . . . . . . . . . . . . . . . . . . . 2.1.1.1 SaaS . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1.2 PaaS . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1.3 IaaS . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1.4 Relacionamento entre modelos de computação em nuvem 2.1.2 Elasticidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Padrões de Projeto de Middleware e Nuvem . . . . . . . . . . . . . . . . . 2.2.1 Arquitetura e Padrões de Projeto para Middleware . . . . . . . . . 2.2.1.1 Middleware Orientado a Objetos . . . . . . . . . . . . . 2.2.1.2 Gerenciamento de Ciclo de Vida . . . . . . . . . . . . . 2.2.1.3 Serviços comuns . . . . . . . . . . . . . . . . . . . . . . 2.2.2 Arquitetura e Padrões de Projeto para Computação em Nuvem . . . 2.2.2.1 Padrões de projeto para computação em nuvem . . . . . 2.3 Cloud Aware Middleware . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.1 Local Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.2 Global Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4 Considerações Finais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Proposta 3.1 Motivação e Objetivos . . . . . . . . . . . . . . . . . 3.2 Requisitos . . . . . . . . . . . . . . . . . . . . . . . . 3.3 Modelo de domínio geral . . . . . . . . . . . . . . . . 3.4 Arquitetura . . . . . . . . . . . . . . . . . . . . . . . 3.4.1 Coordenação . . . . . . . . . . . . . . . . . . 3.4.1.1 Comunicação Publish/subscribe . . . 3.4.1.2 Escalonamento de tarefas periódicas 3.4.2 Compartilhamento de Estado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 17 18 19 20 . . . . . . . . . . . . . . . . . . 21 21 22 22 23 25 27 28 29 30 31 33 35 39 40 41 43 44 44 . . . . . . . . 46 47 48 49 51 52 53 54 55 . . . . . 56 59 62 64 65 . . . . . . . 66 66 67 69 70 70 74 80 . . . . . . . . . . . 81 81 81 82 83 84 85 87 88 90 91 92 Considerações Finais 6.1 Trabalhos Futuros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 94 3.5 3.6 3.7 4 5 6 3.4.2.1 Gerenciamento de ciclo de vida de objetos remotos 3.4.3 Balanceamento de Carga . . . . . . . . . . . . . . . . . . . . Tecnologias utilizadas . . . . . . . . . . . . . . . . . . . . . . . . . . Implantação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Considerações Finais . . . . . . . . . . . . . . . . . . . . . . . . . . Avaliação de Desempenho e Discussão 4.1 Objetivos e Metodologia . . . . . . . . . . . . . . . . . . . . . . . . 4.1.1 Métricas, Parâmetros e Fatores . . . . . . . . . . . . . . . . . 4.1.2 Técnica de avaliação, carga de trabalho e projeto de avaliação 4.2 Resultados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.1 Resultados individuais de cada experimento . . . . . . . . . . 4.2.2 Comparação entre resultados . . . . . . . . . . . . . . . . . . 4.3 Discussão . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Trabalhos Relacionados 5.1 Tecnologias fundamentais usadas pelo ElasticCamid 5.1.1 JGroups . . . . . . . . . . . . . . . . . . . . 5.1.2 Infinispan . . . . . . . . . . . . . . . . . . . 5.2 Trabalhos de Middleware Desenvolvido para Nuvem 5.2.1 Arquitetura Geral de Middleware . . . . . . 5.2.2 Multitenancy . . . . . . . . . . . . . . . . . 5.2.3 Interoperabilidade . . . . . . . . . . . . . . 5.2.4 Elasticidade . . . . . . . . . . . . . . . . . . 5.2.5 Outros requisitos não funcionais de nuvem . 5.2.6 Discussão . . . . . . . . . . . . . . . . . . . 5.2.7 Considerações finais . . . . . . . . . . . . . Referências . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 16 1 Introdução Computação em Nuvem é um paradigma que relaciona sistemas distribuídos e computação utilitária. Assim como concessionárias de energia elétrica, que fornecem um serviço de manutenção e distribuição de energia, provedores de computação em nuvem oferecem uma diversidade de ativos como serviço, onde esses ativos podem ser aplicativos, plataformas de software, bancos de dados virtuais, infraestrutura virtual, hardware e outros (JIN et al., 2010). Da mesma forma que usuários do serviço de energia elétrica, usuários de nuvem pagam pelo uso do serviço e não pela aquisição desses ativos, que é contabilizada de várias formas, como por exemplo tempo de uso, quantidade de dados armazenado, tráfego de rede etc. Uma nuvem é um conjunto de ativos fornecido por um provedor específico e gerenciados pelos seus usuários através de interfaces gráficas, consoles ou Application Programming Interfaces (APIs). Os provedores escondem detalhes relacionados à manutenção e operação dos ativos, geralmente oferecendo algum Service Level Agreement (SLA). Se este ativo for uma plataforma de software, o provedor se encarrega de provisionar a aplicação em uma máquina física ou virtual, replicar esta instalação em múltiplos nós e assim por diante. Caso o ativo seja infraestrutura, o provedor se encarrega de gerenciar máquinas virtuais dos usuários em um pool de máquinas físicas gerenciadas pelo provedor entre outras operações (RIMAL; CHOI; LUMB, 2010). O que torna a computação em nuvem atraente é a diminuição do investimento necessário para construir e manter uma infraestrutura de hardware e software, para desenvolver novos aplicativos e para usar e manter software de terceiros. Empresas como Google oferecem pacotes de software de produtividade e serviços de email (Google Apps for Business) (HERRICK, 2009), acessíveis através da internet em poucos cliques, sem a necessidade de instalar e manter esses aplicativos localmente (MARSTON et al., 2011), em um modelo conhecido como Software as a Service (SaaS). Outros provedores de nuvem como a Amazon (VARIA; MATHEW, 2012) permitem a aquisição de infraestrutura, como máquinas e sistemas de armazenamento virtuais que funcionam de forma similar a uma infraestrutura física, mas sem a necessidade de fazer um grande investimento inicial tanto em aquisição quanto em instalação que é comum em servidores físicos. 1.1. O PROBLEMA 17 Além da vantagem da redução do investimento, o modelo de computação em nuvem permite também evitar o superdimensionamento dos recursos computacionais utilizados. Ativos de um provedor de computação em nuvem podem ser adquiridos e descartados rapidamente. Logo, se é previsto um aumento na utilização do serviço, pode ser solicitado a aquisição de novos ativos. No momento em que estes não forem mais necessários, estes poderão ser descartados e devolvidos para o provedor. Este conceito inovador de computação em nuvem é chamado de elasticidade. Aplicações distribuídas que foram pensadas para o ambiente de nuvem podem se beneficiar do conceito de elasticidade. No modelo tradicional, toda a infraestrutura de software e hardware deve ser dimensionada de antemão para atender requisitos não funcionais como desempenho, escalabilidade, disponibilidade e confiabilidade. Essa infraestrutura teria que ser grande o suficiente para suportar os picos de utilização, mas estaria subutilizada em momentos de ociosidade. Com a elasticidade, a infraestrutura não precisa ser superdimensionada, mas pode ser incrementada ou diminuída de acordo com a demanda de recursos computacionais da aplicação. Esse fato torna os ambientes de computação em nuvem muito mais eficientes no gerenciamento de recursos que infraestruturas tradicionais (MARSTON et al., 2011) (TALUKDER; ZIMMERMAN; A, 2010). 1.1 O Problema A elasticidade não apenas é um dos grandes benefícios para aplicações que se apóiam no modelo de computação em nuvem, mas também um grande desafio para os desenvolvedores. A arquitetura dessas aplicações precisa ser pensada para que estas possam operar de forma eficiente e confiável em um ambiente elástico. Atualmente, é possível desenvolver aplicações elásticas utilizando facilidades específicas de um provedor, sejam essas plataformas ou serviços específicos, ou através do uso de APIs específicas que permitem a gerência desses recursos por parte da aplicação. Provedores de nuvem oferecem diversos modelos de serviço que apóiam o desenvolvimento de software distribuído. Em um deles, chamado Platform as a Service (PaaS), ou Plataforma como Serviço, o ativo gerenciado consiste em uma plataforma de software, que oferece um modelo de programação para a construção de uma aplicação. A vantagem deste modelo é que a plataforma já implementa os mecanismos de elasticidade, fornecendo para a aplicação um framework ou um conjunto de APIs que devem ser usados para fazer coisas como armazenar dados ou tratar requisições externas. A desvantagem é que a aplicação estará fortemente acoplada às APIs, frameworks e serviços específicos oferecidos pelo provedor de PaaS. Um outro modelo utilizado para o desenvolvimento de aplicação é conhecido como Infrastructure as a Service (IaaS), ou Infraestrutura como Serviço. Neste modelo, o provedor fornece uma infraestrutura virtual, composta por servidores, discos rígidos, balanceadores de 1.2. SOLUÇÕES PARCIAIS 18 carga entre outros. O provedor também oferece um console ou API para gerenciar os recursos virtuais da nuvem. A vantagem deste modelo é que o usuário pode definir a arquitetura e a tecnologia utilizada na aplicação e pode estar sempre utilizando as tecnologias mais recentes (RIMAL; CHOI; LUMB, 2010). A desvantagem é que os ajustes necessários por tornar a aplicação elásticas precisam ser realizadas pelo usuário, através da gerência de recursos virtuais através de APIs ou consoles específicos de cada provedor. Para facilitar a implantação de soluções elásticas, provedores de IaaS também costumam oferecer serviços específicos que incluem agentes de monitoramento, balanceadores de carga, sistemas de armazenamento chave/valor entre outros. No entanto, de acordo com o provedor de IaaS, esses serviços específicos podem não estar presentes ou divergir na forma em que funcionam. Existe um esforço para padronizar APIs e serviços de provedores de IaaS. Embora existam diversos padrões para computação em nuvem, sejam estes abertos ou padrões de facto, muitos deles ainda não são maduros o suficiente ou amplamente adotados (LEWIS, 2013). Pelos motivos mencionados acima, é bastante difícil desenvolver uma aplicação que seja executada sobre um provedor de nuvem que possua suporte à elasticidade sem utilizar APIs ou serviços específicos de cada provedor, visto que muitos desses serviços são incompatíveis entre si devido à falta de padronização. Desenvolver esses mecanismos de suporte à elasticidade dentro da própria aplicação distribuída pode ser difícil, dado a uma série de complexidades inerentes que são características da elasticidade. Além das complexidades inerentes, podemos citar as complexidades acidentais que são evidenciadas ao misturar lógica do domínio da aplicação com funcionalidades voltadas para o suporte à elasticidade, violando o princípio de projeto de software conhecido como Separation of Concerns. 1.2 Soluções Parciais Middleware é uma solução ligada diretamente ao desenvolvimento de aplicações distribuídas. Tradicionalmente, middleware tem sido empregado para fornecer um modelo de programação que abstrai diversas complexidades do desenvolvimento de aplicações distribuídas. Middleware pode ser utilizado para prover serviços que tornem transparentes as complexidades associadas a um ambiente elástico. O uso de middleware em nuvens IaaS pode trazer os benefícios encontrados em nuvens PaaS, reduzindo o acoplamento com serviços de um provedor específico e fornecendo uma variedade maior de modelos de programação e tecnologias. Entre os diversos sistemas de middleware propostos que visam resolver o problema da elasticidade e que foram testados em nuvens reais, alguns são voltados a domínios específicos, como é o caso de soluções de computação paralela e em grade (CALHEIROS et al., 2012); alguns dependem de ferramentas específicas que não estão presentes nos serviços de um provedor de nuvem (JAYARAM, 2013); outros apenas propõem recursos que refinam o uso de elasticidade, fornecendo capacidades adicionais (AZEEZ et al., 2010). Em um trabalho anterior do grupo Research Group on Foundations and Applications of 1.3. PROPOSTA 19 Distributed Systems (GFADS)1 , foi proposto um middleware, que utiliza o paradigma Distributed Object Computing Middleware (DOC), denominado Cloud-Aware Middleware (CaMid). Este middleware foi pensado para o ambiente de computação em nuvem e seu principal objetivo é tornar transparente (invisível) a complexidade de gerenciamento da nuvem para o desenvolvedor de aplicação distribuída. Os princípios que guiam a arquitetura do CaMid são: cloud-awareness, ou a capacidade de monitorar e controlar os recursos disponíveis da aplicação; gerenciamento automático, que é a capacidade de manipular recursos sem intervenção humana direta; suporte a aplicações cliente-servidor; transparência de localização e acesso; arquitetura baseada em padrões de projeto (MORAIS; LIBERALQUINO; ROSA, 2013). O CaMid foi pensado para gerenciar vários aspectos de uma nuvem IaaS, incluindo aspectos relacionados à elasticidade. Desta forma, o Elastic Cloud-Aware Middleware (eCaMid) poderia ser usado diretamente por aplicações que utilizam o modelo de objetos distribuídos que serão implantadas no ambiente de IaaS ou como blocos fundamentais de um PaaS que usa esse mesmo modelo. No entanto, a sua primeira implementação não possui mecanismos de tolerância a falhas, como tolerância a falha temporária ou permanente de um nó, assim como balanceamento de carga e mecanismos mais eficientes de comunicação entre nós. 1.3 Proposta Este trabalho propõe uma extensão à implementação e arquitetura do CaMid, chamada eCaMid, que aprimora os mecanismos existentes para ambientes elásticos. Foram adicionados mecanismos de comunicação em grupo, replicação e balanceamento de carga, que permitem tomar vantagem da adição dinâmica de nós a uma infraestrutura virtual, assim como tratar de forma transparente as falhas de comunicação, ou garantir a consistência das informações quando os mesmos nós são removidos, seja de forma intencional ou por ocasião de falha. Os mecanismos de suporte à elasticidade do eCaMid não dependem de um provedor específico de IaaS, pois todas as funcionalidades foram desenvolvidas internamente ao próprio middleware. O modelo de programação do antigo CaMid foi estendido para permitir o suporte a objetos stateful, interceptadores, a troca de mensagens entre componentes através de um modelo publish/subscribe e a execução de tarefas periódicas, coordenadas entre vários nós. Essas novas funcionalidades apóiam tanto o desenvolvimento de aplicações distribuídas quanto à extensão de funcionalidades internas ao middleware. A principal contribuição deste trabalho foi mostrar os benefícios da utilização de comunicação em grupo, replicação e balanceamento de carga em uma arquitetura de middleware orientado a objeto, tornando-a mais adequada para a utilização em ambientes elásticos de computação em nuvem. 1 http://www.gfads.org/ 1.4. ESTRUTURA DA DISSERTAÇÃO 1.4 20 Estrutura da Dissertação Este trabalho está dividido em 6 capítulos, incluindo este capítulo introdutório. Capítulo 2: introduz conceitos básicos úteis para compreender a proposta deste trabalho, como uma explanação do conceito de nuvem e elasticidade, uma série de padrões de projeto utilizados em middleware e em computação em nuvem e uma breve explanação sobre a arquitetura do CaMid, Capítulo 3: apresenta a arquitetura do eCaMid e como as novas funcionalidades poderão ser utilizadas em um ambiente elástico, Capítulo 4: apresenta uma avaliação experimental do eCaMid em um cenário onde a elasticidade é utilizada, Capítulo 5: este capítulo apresenta os trabalhos relacionados que também procuram resolver de alguma forma a problema da elasticidade, e Capítulo 6: apresenta algumas considerações finais sobre os resultados obtidos neste trabalho e propõe trabalhos no futuro. 21 2 Conceitos Básicos Neste capítulo, introduziremos as principais tecnologias necessárias ao entendimento do eCaMid. Na primeira seção, faremos uma breve discussão sobre o que é computação em nuvem, o seu modelo de negócio, as principais categorias de serviço de computação em nuvem e a relação entre essas categorias de serviço, com foco em SaaS, PaaS e IaaS. Faremos uma conceituação do que é elasticidade, qual a sua importância para computação em nuvem e como este tipo de solução é implantada nas categorias de serviço discutidas anteriormente. Na seção seguinte, faremos uma discussão sobre o que é middleware e quais padrões arquiteturais e de projeto apóiam o seu desenvolvimento. Faremos uma discussão também de vários padrões de projeto que são relevantes para o contexto de aplicação em nuvem. Seguindo esta seção, apresentaremos o CaMid, quais seus objetivos e princípios, qual sua a arquitetura, e como esta é apoiada sobre os padrões discutidos na seção anterior. Faremos também uma discussão sobre as deficiências arquiteturais e de implementação do CaMid em relação à elasticidade. 2.1 Computação em Nuvem Segundo FOX et al. (2009), computação em nuvem "é a materialização da ideia de computação utilitária, que tem o potencial de mudar grande parte da indústria de TI, fazendo com que produtos de software sejam oferecidos como serviço e reduzindo os imensos gastos com hardware e pessoas para operarem esses equipamentos". Computação em nuvem pode ser oferecida como uma série de serviços, que oferecem ativos de várias formas, de softwares como suítes de produtividade como é o caso do serviço Google App Engine (GAE) (HERRICK, 2009) à plataformas de software e infraestruturas virtuais complexas, como Amazon Web Services (AWS) (VARIA; MATHEW, 2012). Quando estes serviços são oferecidos através da Internet, por uma entidade externa, este serviço é chamado de nuvem pública, mas quando é oferecido por um departamento ou setor de uma mesma corporação, a oferta de serviço é chamada de nuvem privada. Computação em nuvem nasceu da necessidade de se operar uma infraestrutura com eficiência através de recursos de software e hardware escaláveis, em resposta à necessidade de 2.1. COMPUTAÇÃO EM NUVEM 22 negócios que precisam desenvolver rapidamente aplicações com alto desempenho, escalabilidade e disponibilidade, sejam estas aplicações analíticas ou aplicações móveis que precisam de respostas em tempo real (MARSTON et al., 2011). Conforme várias empresas de tecnologia ganhavam maturidade na utilização de tecnologias como virtualização e Service Oriented Architecture (SOA), foi possível construir infraestruturas robustas onde operações de rotina, como aquisição de servidores virtuais, aconteciam de forma automática e transparente (FURHT, 2010) (JIN et al., 2010). Após o esforço de automatizar a gerência desses ativos, foram criados modelos de monetização para que estes pudessem ser disponibilizados como serviços. 2.1.1 Categorias de serviço de nuvem Dependendo do ativo oferecido em um serviço, podem existir vários tipos de ofertas de computação em nuvem. Há várias taxonomias de computação em nuvem descritas na literatura, como Hardware as a Service, Data as a Service, Storage as a Service, Business as a Service e assim por diante. No entanto, dentre todas as taxonomias descritas, três estão sempre presentes: SaaS, PaaS e IaaS. 2.1.1.1 SaaS A primeira categoria, Software as a Service (SaaS), trata de aplicações que são disponibilizadas como serviços para um usuário específico, um grupo de usuários ou uma empresa. A exemplo de aplicativos SaaS, temos o Dropbox DRAGO et al. (2012), um sistema de armazenamento e compartilhamento de arquivos; o já mencionado Google Apps for Business HERRICK (2009), um pacote de software que inclui e-mail, criação de documentos como textos e apresentações e compartilhamento de arquivos; redes sociais como Facebook1 , que permitem o compartilhamento de mensagens, imagens e videos; serviços de streaming, que incluem o Grooveshark2 e Netflix3 . Há várias características que geralmente estão presentes em aplicativos fornecidos como SaaS: todos estes são acessíveis pela Internet, através de vários dispositivos, permitem algum tipo de troca de informações entre os seus usuários ou possuem modelos de assinatura que permitem pagar mais para obter algum tipo de vantagem no serviço. Esses aplicativos geralmente possuem requisitos não funcionais complexos, como disponibilidade, escalabilidade, desempenho e confiabilidade. Além destes requisitos, esses aplicativos precisam ser constantemente atualizados, corrigindo defeitos rapidamente e oferecendo novas funcionalidades e recursos. Desenvolver plataformas de software e hardware que sejam capazes de suportar esses requisitos não funcionais é um dos grandes desafios para os provedores de SaaS. 1 http://www.facebook.com 2 http://www.grooveshark.com 3 http://www.netflix.com 2.1. COMPUTAÇÃO EM NUVEM 23 Figura 2.1: Arquitetura dos serviços de nuvem oferecidos pela Google (JIN et al., 2010) 2.1.1.2 PaaS A segunda classificação de serviço oferecido em computação em nuvem, Platform as a Service (PaaS), consiste em uma plataforma de software que um framework ou uma API que possibilita o desenvolvimento de aplicações distribuídas. Usuários desses serviços implantam a aplicação na plataforma e definem parâmetros que informam a quantidade de recursos necessários, enquanto o provedor do serviço se encarrega de provisionar a infraestrutura necessária para os níveis desejados de Quality of Service (QoS). Cada oferta de PaaS varia bastante de provedor para provedor conservando, contudo, algumas semelhanças. Discutiremos sobre dois populares serviços de PaaS, GAE (SANDERSON, 2009) e Heroku (KEMP; GYGER, 2013), para entender como funcionam as ofertas de PaaS. O serviço GAE, Figura 2.1, fornece ao desenvolvedor uma plataforma voltada para aplicações Web. Cada aplicação web é executada em um sandbox, um ambiente que restringe o acesso da aplicação a funcionalidades como acesso a arquivos, limitando-a a utilizar requisições HTTP para páginas presentes na Web, na própria aplicação ou no GAE. Para utilizar outros serviços, como armazenamento de dados, e-mail, XMPP e outros, deve-se utilizar as APIs fornecidas pelo serviço, que por sua vez se encarrega de alocar recursos e distribuir as várias partes da aplicação de forma transparente, garantindo sua escalabilidade. O usuário é cobrado pelos recursos que utiliza do serviço. Google não revela em detalhes a arquitetura de sua oferta de PaaS, e não existe na literatura uma descrição detalhada dos componentes e como estes interagem para tornar a aplicação disponível. É possível que a solução utilize uma espécie de middleware que provê acesso a todas APIs oferecidas e de algum outro serviço que trata de distribuir a aplicação entre 2.1. COMPUTAÇÃO EM NUVEM 24 várias máquinas, que podem ser físicas ou virtuais. Pelo modelo de cobrança adotado no GAE, é possível verificar que cada porção da aplicação é monitorada, desde o acesso a sua datastore (chamada Bigtable), que contabiliza número de leituras e escritas, requisições HTTP para serviços externos, logging e outros. O usuário, contudo, não tem controle sobre a quantidade de recursos utilizados numa aplicação GAE e pode apenas indicar o valor máximo que deseja pagar pelo serviço. Este tem a autonomia de ditar quantas instâncias serão necessárias e qual a forma de balanceamento de carga usada, por exemplo. A plataforma Heroku suporta aplicações Web escritas em diferentes linguagens de programação (Java, Ruby, Python, Node.js e outras), onde essa aplicação deve ser dividida em vários pedaços a serem executados em containers chamados dynos. De forma similar ao GAE, um dyno representa um sandbox ou container que isola uma aplicação de outra em uma estrutura virtual, mas sem as mesmas restrições que foram mencionadas anteriormente no GAE. Existem dois tipos principais de dynos, um Web Dyno, que é responsável por receber requisições web externas e um Worker Dyno que executa algum processo auxiliar, como uma rotina batch ou um processo que consome mensagens de uma fila. Dessa forma é possível criar aplicações que dividem tarefas entre diversos processos distribuídos. Além dos dois tipos de dynos mencionados, o Heroku oferece outros dynos especializados que atuam como bancos de dados e servidores de mensagem, por exemplo (KEMP; GYGER, 2013). Cada dyno é executado em uma stack, um conjunto de máquinas virtuais que contém configurações idênticas – sistema operacionais na mesma versão, com versões específicas das linguagens e softwares utilitários da plataforma instalados. Um gerenciador de processos distribuídos é utilizado para escalonar os dynos em cada máquina virtual do stack. Cada usuário pode verificar quais dynos estão em execução em um determinado momento. O modelo de cobrança utilizado no Heroku é mais simples do que aquele utilizado no GAE. O usuário é cobrado por cada dyno utilizado e um preço mais específico para os dynos especializados. O usuário no Heroku tem mais controle dos recursos que utiliza, que determina quantos dynos serão utilizados e de que tipo. Além disso o Heroku também oferece APIs de serviços para que os dynos sejam monitorados pelo usuário e agentes que reinicializam dynos que se encontrem inoperantes ou com o desempenho degradadao (KEMP; GYGER, 2013). Diferente da plataforma GAE, que restringe à aplicação o uso de APIs mais restritas e uma arquitetura específica, o Heroku dá total liberdade ao usuário de usar qualquer tecnologia desde que seja compatível com as configurações definidas no stack. Em contrapartida, o framework ou tecnologia utilizados devem ser adaptar ao ambiente fornecido pelo Heroku, de forma similar ao que acontece com ofertas de IaaS. O diferencial do Heroku em relação aos serviços de IaaS é que este oferece um ambiente pré-configurado, e o gerenciamento e a implantação das aplicações seguem uma arquitetura de processos. Além dessas ofertas de PaaS, outros serviços merecem destaque. A plataforma Elastic Beanstalk é parte do catálogo AWS e é composto de várias máquinas virtuais pré-configuradas 2.1. COMPUTAÇÃO EM NUVEM 25 com software específico, com serviços de escalabilidade automática (VARIA; MATHEW, 2012). A plataforma Tsuru4 é uma implementação open source do Heroku, que pode ser implantada em instalações privadas de IaaS. De forma similar, Cloud Foundry5 é outro PaaS open source voltado para infraestruturas privadas. De forma geral, podemos observar que os PaaS podem ser compostos de middleware específico e de um serviço de gerenciamento que é responsável por provisionar este middleware em uma infraestrutura física ou virtual. 2.1.1.3 IaaS Além das ofertas de PaaS, ainda há provedores que fornecem infraestrutura ao usuário de nuvem. Essas infraestruturas utilizam virtualização, uma tecnologia que permite simular o funcionamento de hardware através de software. Como os ativos virtuais são constituídos de dados, eles podem ser armazenados, copiados e versionados. O público alvo das ofertas de Infrastructure as a Service (IaaS) são organizações que precisam implantar aplicações de alta escalabilidade com alto controle sobre a tecnologia utilizada, sem ter que lidar com o custo de aquisição, implantação e manutenção de hardware. Diferentemente das ofertas de PaaS, os ativos oferecidos pelos serviços de IaaS são mais homogêneos, e geralmente são servidores, discos rígidos, redes privadas e balanceadores de carga. Além desses ativos, os provedores costumam oferecer serviços mais específicos, como o Amazon Cloudwatch (VARIA; MATHEW, 2012), da suíte AWS, que é usada para monitorar os recursos da aplicação e servir de métrica para outros serviços da AWS, como Auto Scaling. Os serviços específicos costumam ser exclusivos de cada provedor, alguns oferecem serviços ligeiramente similares. Todos os provedores de nuvem disponibilizam uma API que pode ser usada para gerenciar esses ativos. Os serviços disponibilizados pelos provedores de IaaS podem ser divididos em 4 categorias: processamento, armazenamento, rede virtual, e serviços específicos. O serviço de processamento é a base de todos os serviços de IaaS. Este permite o gerenciamento, monitoramento, cópia e provisionamento de servidores virtuais. O provedor oferece os servidores em vários tamanhos, dependendo da quantidade de processadores, memória RAM e capacidade de armazenamento. Usuários e fornecedores externos fornecem pacotes que contém um sistema operacional e uma distribuição de software, conhecidos como imagens, que também são gerenciadas pelo provedor de IaaS. Todos os provedores de IaaS oferecem o serviço de poder computacional, incluindo nuvens públicas (AWS) e privadas (Openstack6 , Opennebula7 , Eucalyptus8 . A segunda categoria de serviço IaaS trata de armazenamento de dados. É comum que o provedor ofereça este serviço de duas formas distintas: como um serviço de gerenciamento 4 http://www.tsuru.io 5 http://cloudfoundry.org 6 http://www.openstack.org 7 http://www.opennebula.org 8 http://www.eucalyptus.com 2.1. COMPUTAÇÃO EM NUVEM 26 de blocos virtuais, como o AWS Elastic Block Store, Openstack Cinder e Eucalyptus Storage Controller; ou um serviço de armazenamento chave-valor, tais como AWS Simple Storage Service, Openstack Swift e Eucalyptus Walrus. O primeiro é utilizado como discos rígidos virtuais que aumentam a capacidade de armazenamento de uma máquina virtual, enquanto o armazenamento de chave-valor pode ser usado para armazenar imagens de máquinas virtuais ou diretamente por aplicações distribuídas, sob a forma de bancos de dados não relacionais. Serviços de armazenamento de bloco dependem de estruturas da infraestrutura física, como Storage Area Networks (SANs), enquanto servidores de armazenamento chave-valor são bancos de dados completos, particionáveis e de alta escalabilidade. Além da capacidade de oferecer máquinas virtuais e armazenamento, os provedores de nuvem também oferecem redes virtuais, como é o caso dos serviços Amazon Virtual Private Cloud (Amazon VPC) (VARIA; MATHEW, 2012) e Openstack Neutron (OPENSTACK CLOUD ADMINISTRATOR GUIDE, 2014). Esses software permitem a emulação de redes virtuais, como roteadores e switches qua atuam na camada de rede, dispositivos de firelwall e outros. Através desse softwares é possível separar a infraestrutura em várias camadas, como é o caso de separar servidores de aplicação e banco de dados em camadas distintas. Existe uma grande variedade de serviços específicos fornecidos por fornecedores de IaaS. O provedor AWS possui um grande catálogo de serviços, como balanceamento de carga, provisionamento automático (auto scaling), monitoramento (Cloudwatch) entre outros. Outros fornecedores de IaaS públicos, como Google Compute Cloud 9 oferecem serviços similares. No espaço de fornecedores de IaaS privados, temos Eucalyptus e Openstack que fornecem balanceamento de carga através do Network Controller e Neutron, respectivamente. Nem todos os serviços mencionados são unanimidade em provedores de IaaS. Opennebula e Cloudstack, por exemplo, oferecem apenas os serviços de poder computacional e armazenamento (apenas discos virtuais). Para que uma aplicação utilize o potencial oferecido pela nuvem, ela deve conhecer quais as facilidades oferecidas pelo provedor; para se manter independente, é necessário que esta possua mecanismos para se adaptar às diferentes ofertas de serviço. A maioria das iniciativas de padronizar a Computação em Nuvem estão voltadas para o modelo de IaaS, por conta da similaridade dos serviços oferecidos por diferentes provedores, de acordo com a categoria do serviço. Temos Open Cloud Computing Interface (OCCI) 10 , uma iniciativa para padronizar as APIs voltadas para o controle de máquinas virtuais; Cloud Data Management Interface (CDMI) 11 , uma API para serviços de armazenamento de dados; Open Virtualization Format (OVF) 12 que define formatos específicos para os metadados de máquinas virtuais, permitindo que estas sejam migradas de um provedor para outro (LEWIS, 2013). 9 https://cloud.google.com/products/compute-engine/ 10 http://occi-wg.org 11 http://www.snia.org/cdmi 12 http://www.dmtf.org/standards/ovf 2.1. COMPUTAÇÃO EM NUVEM 27 Figura 2.2: Relacionamento entre modelos de computação em nuvem (RIMAL; CHOI; LUMB, 2010) 2.1.1.4 Relacionamento entre modelos de computação em nuvem É possível observar uma possível relação entre as ofertas de SaaS, PaaS e IaaS. O modelo de SaaS precisa ser capaz de suportar uma grande quantidade de usuários e manter alta disponibilidade, uma vez que seus serviços podem estar sendo usados por um usuário em qualquer parte do mundo, em diferentes horários. Para isso, uma oferta de SaaS precisa ser construída sobre uma plataforma que forneça esses requisitos, como o oferecido em um modelo de PaaS. Este, por sua vez, precisa de uma infraestrutura eficiente que suporte a elasticidade e provisionamento rápido de recursos, como numa oferta de IaaS. Essa relação entre serviços pode ser ilustrada na Figura 2.2. Não necessariamente um serviço oferecido por um modelo está apoiado por outro modelo de computação em nuvem. Não há evidências de que o GAE opere sobre um serviço de IaaS. Na verdade, o GAE foi desenvolvido anos depois da plataforma mencionada. Contudo, existem provedores públicos de PaaS que utilizam a infraestrutura de provedores de IaaS, como é o caso do Heroku, que opera sobre a infraestrutura provida pela AWS. O Software chamado CloudApp 13 é uma aplicação que segue o modelo SaaS, especializada em compartilhamento de imagens, documentos, video e outros ativos, através da plataforma Heroku. Outros provedores de SaaS, 13 http://www.getcloudapp.com/ 2.1. COMPUTAÇÃO EM NUVEM 28 como Netflix 14 , possuem uma plataforma própria e preferem utilizar a infraestrutura da AWS diretamente. 2.1.2 Elasticidade Uma das consequências de computação em nuvem foi a conversão de despesas de capital em despesas operacionais (FOX et al., 2009), direcionando os investimentos que antes eram realizados em hardware e soluções de alto poder computacional para despesas de pessoal e ferramentas para gerenciar o potencial de computação em nuvem. Este fator se deve a elasticidade, uma vez que é possível obter recursos da nuvem e depois descartar uma parte quando estes não estão sendo utilizados. Em uma infraestrutura tradicional, existe o custo associado à aquisição de recurso (hardware), instalação e operação da infraestrutura. Esta deve ser bem planejada para evitar tanto o risco de se ter uma infraestrutura saturada ou subutilizada. Geralmente, o uso médio do poder computacional da infraestrutura física costuma variar entre 5% e 20% (SIEGELE, 2008), mas durante picos de utilização, o uso do poder computacional pode aumentar numa dimensão de duas a dez vezes. Supondo que durante uma parte do dia sejam necessários 500 servidores para atender a demanda de acesso de uma aplicação (pico), mas no resto do tempo apenas 100 servidores sejam necessários, com uma média de 300 servidores necessários por dia; para se manter disponível e não degradar o desempenho da aplicação durante o pico de utilização, seria necessária uma infraestrutura 1.7 vezes maior do que a média de uso dos servidores (FOX et al., 2009). O paradigma de computação em nuvem, devido à elasticidade, oferece uma forma de mitigar o risco involvido no dimensionamento da infraestrutura, fornecendo a possibilidade de adicionar ou remover novas máquinas virtuais em minutos, ao invés de semanas ou meses em infraestruturas tradicionais. Utilizar a elasticidade com eficiência não é uma tarefa fácil. BABAR; CHAUHAN (2011) menciona os desafios de migrar uma aplicação chamada Hackystat15 , desenvolvida em uma infraestrutura tradicional, para uma infraestrutura ou plataforma fornecida por um provedor de nuvem. Para escolher a arquitetura da solução, quatro requisitos foram levados em conta. O primeiro requisito está relacionado à possibilidade de aumentar ou diminuir o tamanho da nuvem de acordo com critérios de desempenho. O segundo requisito estava relacionado à portabilidade da aplicação para diferentes provedores de nuvem, que deveriam suportar as tecnologias utilizadas pela aplicação. O terceiro requisito se referia a portabilidade de dados (persistência), aos mecanismos de persistência de diferentes provedores. O quarto requisito se referia a necessidade de uma visão única do sistema: embora a infraestrutura fosse dinâmica, com vários componentes replicados, deveria ser possível acessar todas essas réplicas como um único componente. 14 http://www.netflix.com 15 http://csdl.ics.hawaii.edu/research/hackystat/ 2.2. PADRÕES DE PROJETO DE MIDDLEWARE E NUVEM 29 Para atender esses requisitos foram realizadas modificações na arquitetura da Hackystat. Foram utilizados os serviços de IaaS, uma vez que ofertas de PaaS não possibilitavam utilizar as tecnologias utilizadas no Hackystat. Foi necessário separar os componentes de lógica de negócio e persistência para que fosse possível criar réplicas do primeiro e o segundo fosse adaptável a múltiplos provedores de IaaS. Além da persistência, foi criado um componente que orquestrava as requisições do Hackystat para as réplicas criadas em diferentes máquinas virtuais (BABAR; CHAUHAN, 2011). 2.2 Padrões de Projeto de Middleware e Nuvem Aplicações executadas no ambiente de computação em nuvem estão dentro do grande grupo que compreende os sistemas distribuídos. O que diferencia sistemas distribuídos de aplicações tradicionais é que um único sistema está dividido em um ou mais processos, que se comunicam através de mensagens, que possuem espaços de memória distintos e interagem juntos com um objetivo único (GHOSH, 2010). As vantagens de um sistema distribuído sobre sistemas monolíticos são: localização geográfica distribuída, em que várias aplicações em diferentes localidades podem trocar informações entre si; desempenho e escalabilidade, onde tarefas que seriam realizadas em um processo podem ser divididas entre vários; compartilhamento de recursos, onde múltiplos processos compartilham recursos em comum, como é o caso de bancos de dados compartilhados; e tolerância a falhas, uma vez que a falha em um processo pode ser compensada pela existência de um outro processo redundante (SCHMIDT et al., 2013) (VÖLTER; KIRCHER; ZDUN, 2005). Apesar de todos os benefícios, o desenvolvimento de sistemas distribuídos apresenta uma série de desafios. Existem complexidades inerentes e acidentais relacionadas a sistemas distribuídos. Entre as complexidades inerentes temos a necessidade de lidar com falhas parciais de um sistema, qualidade de serviço, deadlock distribuídos, sincronização entre outros. Entre as complexidades acidentais estão as limitações das ferramentas de de desenvolvimento de software para lidar com esse cenário, além da falta de APIs portáveis entre diferentes infraestruturas. Um outro problema é a reinvenção e redescobertas de conceitos e técnicas voltadas para desenvolvimento de aplicações distribuídas: existe na indústria de sistemas distribuídos vários protocolos, bibliotecas, sistemas operacionais entre outros que resolvem os mesmos problemas e são geralmente incompatíveis entre si (SCHMIDT et al., 2013). Muitas dessas soluções são proprietárias, sem utilizar padrões abertos já difundidos na indústria. Tradicionalmente, Middleware tem sido empregado para tornar transparentes as complexidades inerentes de um sistema distribuído, fornecendo, ao mesmo tempo, um modelo de programação mais abstrato que pode ser utilizado pelos desenvolvedores desses sistemas. Existem várias categorias de Middleware, dependendo do tipo de modelo de programação utilizado: O modelo de Remote Procedure Call (RPC) torna a comunicação entre dois processos bastante similar à invocação de funções, onde o cliente fornece uma série de parâmetros e o 2.2. PADRÕES DE PROJETO DE MIDDLEWARE E NUVEM 30 servidor retorna uma resposta; o modelo DOC, é uma especialização do modelo RPC, onde as primitivas utilizadas são invocações de métodos de objetos, onde estes podem possuir estado e ser compostos de outros objetos; e o modelo Message Oriented Middleware (MOM), onde filas de mensagem são utilizadas como primitiva, onde produtores e consumidores de mensagens utilizam essas filas para se comunicar de indiretamente (VÖLTER; KIRCHER; ZDUN, 2005). O desenvolvimento de Middleware tem sido fortemente apoiado por padrões de projetos. Estes representam um conjunto de boas práticas no projeto do software, pois já foram testados e provados ao longo dos anos, tornando-se soluções refinadas. Padrões de projeto também são utilizados para compor um vocabulário utilizado para compartilhar conhecimento e experiência sobre possíveis problemas computacionais e suas soluções (GAMMA et al., 1993). Existe uma extensa literatura sobre a aplicação desses padrões a sistemas distribuídos: SCHMIDT et al. (2013) inclui padrões para lidar com concorrência e programação de redes; VÖLTER; KIRCHER; ZDUN (2005) mostra os componentes fundamentais para a construção de Middleware orientado a objeto; e HOHPE; WOOLF (2004) menciona um conjunto de padrões para integrar diferentes sistemas utilizando mensagens e comunicação assíncrona. Existem padrões de projeto e de arquitetura para aplicações distribuídas que utilizam o paradigma de computação em nuvem (WILDER, 2012) (HOMER et al., 2014) (REESE, 2009). WILDER (2012) ilustra diversas soluções para problemas comuns de computação em nuvem, como escalabilidade horizontal, auto-escalabilidade, consistência eventual, tolerância a falhas, entre outros. O foco deste trabalho está voltado para o desenvolvimento de aplicações que nasceram neste ambiente e precisam ser pensadas para tirar proveito de todos os benefícios concedidos pelo paradigma de computação em nuvem. 2.2.1 Arquitetura e Padrões de Projeto para Middleware Enquanto middleware pode ser definido de várias formas e é descrito de várias maneiras na literatura, podemos utilizar uma arquitetura genérica, baseada em camadas, para descrever sua estrutura, como é ilustrada na figura 2.3. Entre as camadas dispostas na figura, podemos evidenciar os dispositivos de Hardware e Sistemas Operacionais e Protocolos, que compreendem todas as APIs e mecanismos de baixo nível que envolvem a comunicação de rede e entre processos de um mesmo sistema operacional. A última camada, constituída pela aplicação, compreende toda a lógica de domínio, que por sua vez utiliza todas as camadas abstratas de middleware para realizar comunicação. As camadas que se localizam entre a camada de infraestrutura e a serviços específicos compreendem todas as funcionalidades que estão disponíveis em um middleware. A camada de infraestrutura, é responsável por encapsular mecanismos de baixo nível de um sistema operacional e programação de rede. Entre os mecanismos encapsulados, temos a programação de sockets, gerenciamento de eventos e concorrência. Esta camada também precisa lidar com diferenças entre APIs de sistemas operacionais. A camada de infraestrutura oferece para a camada 2.2. PADRÕES DE PROJETO DE MIDDLEWARE E NUVEM 31 Figura 2.3: Arquitetura Genérica de Middleware de distribuição uma série de componentes reusáveis, independentes de sistema operacional, que fornecem mecanismos de entrada e saída de dados e gerenciamento de conexões (SCHMIDT, 2002). A camada de distribuição esconde todos mecanismos de gerenciamento de conexões e entrada e saída de dados para oferecer abstrações de alto nível como filas de mensagens e objetos remotos. Utilizando essas abstrações é possível desenvolver aplicações distribuídas que funcionam de forma similar a aplicações monolíticas, que são executadas sobre um único processo (SADJADI; MCKINLEY, 2003). A camada de serviços comuns reside sobre a camada de distribuição, oferecendo funcionalidades ligadas a requisitos não funcionais da aplicação, como tolerância a falhas, qualidade de serviço, logging, persistência, segurança e transações. Enquanto a camada de distribuição se preocupa com particularidades do modelo de programação, a camada de serviços específicos realiza a gerência de vários recursos distribuídos entre vários processos, tendo uma visão do todo. Os serviços oferecidos nesta camada podem ser reusados em diferentes tipos de aplicações, independentemente de seu domínio. Os serviços específicos tratam de funcionalidades voltadas a um determinado domínio, voltados a requisitos funcionais e não funcionais. Entre os serviços específicos utilizados em middleware temos o controle de transações financeiras, controles de aviação (radar, navegação, controle de armamento), entre outros (SCHMIDT, 2002). 2.2.1.1 Middleware Orientado a Objetos Middleware Orientado a Objetos (MOO) é utilizado para comunicação cliente-servidor que utiliza objetos como principal abstração. Existem várias tecnologias de MOO, como CORBA, RMI, EJB, DCOM (EMMERICH; KAVEH, 2002). Embora esta tecnologia seja aplicável em muitos domínios distintos, é comum encontrá-la em aplicações cliente-servidor multi-camadas, como pode ser observado na figura 2.4. Aplicações multi-camada utilizam comunicação síncrona 2.2. PADRÕES DE PROJETO DE MIDDLEWARE E NUVEM 32 Figura 2.4: Arquitetura de aplicação multi-camadas (request-reply) entre camadas, com suporte a serviços intermediários tais como balanceamento de carga, segurança e gerenciamento de transações GORTON (2011). O cliente manipula objetos localmente em sua aplicação quando, de fato, este objeto está localizado no lado servidor. O objeto do lado do cliente é um Proxy, um objeto que não contém nenhuma lógica de domínio, que delega todas as invocações de métodos executadas no cliente para o objeto localizado no servidor. Este objeto se chama Remote Object, um objeto que possui lógica de domínio, pode possuir estado e tem seu ciclo de vida controlado pelo servidor. Um Proxy delega requisições de cliente a um componente conhecido como Requestor. Este transforma a requisição de um cliente em uma mensagem, que é encapsulada e delegada a um componente chamado Client Request Handler. Este componente, por sua vez, se encarrega de entregar a mensagem ao servidor utilizando mecanismos de rede. De forma similar, no lado servidor, um componente chamado Server Request Handler recebe uma mensagem e entrega a mesma ao Invoker, que a desencapsula, obtém a instância do Remote Object, e faz uma chamada de método local a este objeto. Os componentes chamados Marshallers são responsáveis por codificar as mensagens para um stream de bytes e decodificar este stream de bytes em uma mensagem, que será entregue entre do cliente para o servidor e vice-versa. Este processo pode ser observado com a figura 2.5 (VÖLTER; KIRCHER; ZDUN, 2005). O conjunto formado pelo Requestor, Invoker, Client Request Handler e Server Request Handler são componentes básicos de uma estrutura maior, chamada de Broker. Além da comunicação propriamente dita, o Broker também está encarregado de gerenciar o ciclo de vida dos objetos e fornecer ganchos para as chamadas dos serviços específicos e de domínio. 2.2. PADRÕES DE PROJETO DE MIDDLEWARE E NUVEM 33 Figura 2.5: Invocação de método remoto em um middleware orientado a objetos 2.2.1.2 Gerenciamento de Ciclo de Vida Um Remote Object funciona de forma similar a um objeto comum em uma linguagem orientada a objetos, com suporte à composição, delegação herança, polimorfismo e outras características. O que diferencia Remote Objects de objetos locais é que o estado destes, por conta da dinâmica da comunicação entre cliente e servidor, precisa ser gerenciado pelo Broker. Em um ambiente de uma linguagem orientada a objetos, podem ser utilizados mecanismos de alocação de memória manual ou um garbage collector, que retira da memória objetos que não estão sendo utilizados. Em uma aplicação cliente-servidor, podem haver milhares de clientes e Remote Objects. Contudo, um cliente pode ser desconectado por conta de uma falha interna na rede. O Broker, no entanto, não pode simplesmente descartar o objeto por conta de uma queda de conexão, pois o cliente poderia tentar se reconectar e continuar a operação de negócio que estava realizando antes. Ao mesmo tempo, a parte servidor do Broker não pode manter o objeto na memória indefinidamente, pois isso poderia provocar o esgotamento de recursos do sistema operacional e consequentemente na queda do servidor. Por esse motivo, Remote Object s são classificados de três formas diferentes, como Static Instances, Per-Request Instances e Client-Dependent Instances (VÖLTER; KIRCHER; ZDUN, 2005). Static Instances, são objetos que preservam seu estado independentemente do cliente que os consulta e sua memória é preservada durante toda a existência do Broker. Esta estratégia é útil quando a vida deste objeto está ligada diretamente a existência de um dispositivo físico ou processo. No entanto, a existência de muitas Static Instances podem levar ao esgotamento 2.2. PADRÕES DE PROJETO DE MIDDLEWARE E NUVEM 34 de memória do sistema operacional. Um outro problema relacionado a Static Instances é que estes devem manter seu estado consistente mesmo após inúmeras chamadas remotas de diversos clientes, levando a problemas de concorrência. Uma forma de evitar totalmente os problemas de concorrência e esgotamento de memória de Static Instances, é não preservar nenhum estado no Remote Object. Per-Request Instances são objetos que são criados no escopo de uma chamada remota de método. Dessa forma, esses PerRequest Instances podem ser acessados livremente sem problemas de concorrência, consistência ou esgotamento de memória. A desvantagem de sua utilização é que pode existir a necessidade de guardar estado dentro da aplicação, tornando esta estratégia inútil para esta finalidade. Uma terceira classificação representa o meio termo entre o uso de Static Instances e Per-Request Instances. Client-Dependent Instances representam objetos que existem pelo tempo de vida de um cliente. Estes objetos são criados quando um cliente inicia uma conexão com a aplicação e destruídos quando essa conexão é terminada. Client-Dependent Instances reduzem os problemas de concorrência se comparados a um Static Instances, pois este objeto será acessado por um único cliente. As desvantagens dessa abordagem é que se existirem centenas de clientes, centenas de Client-Dependent Instances serão criados. O Broker também não pode certeza absoluta de quando uma conexão é terminada, pois esta pode ser resultado de uma falha de comunicação na rede e não de uma desconexão. Um outro problema é que Client-Dependent Instances não estão totalmente imunes a problemas de concorrência, pois uma aplicação pode ser acessada por múltiplas interfaces utilizando uma mesma conexão. Além das estratégias básicas, o Broker pode utilizar diferentes mecanismos de gerenciamento de recursos dependendo da estratégia de ciclo de vida utilizada. O primeiro mecanismo Lazy Acquisition (VÖLTER; KIRCHER; ZDUN, 2005) se refere em adiar a criação de um Remote Object apenas quando uma chamada para este é realizada. Esse mecanismo faz com que o estado de um Remote Object somente seja alocado na memória quando este for realmente ser utilizado. Este padrão é útil para todas as estratégias de ciclo de vida de objetos. Um segundo mecanismo de gerenciamento de recursos é o uso de Pooling (VÖLTER; KIRCHER; ZDUN, 2005), ou a criação de um pool de objetos que podem ser reutilizados. Este mecanismo evita o overhead causado pela criação e destruição de um objeto remoto, otimizando a utilização de recursos do sistema operacional. Pooling é melhor utilizado para objetos que não possuem identidade ou estado e são tratados de forma igual, como é o caso de Per-Request Instances. Pooling pode também ser utilizado para objetos com estado, desde que este seja alocado dinamicamente pelo Broker. O terceiro mecanismo de gerenciamento de recursos se chama Leasing (VÖLTER; KIRCHER; ZDUN, 2005) e consiste em atribuir um tempo de expiração para a alocação de um Remote Object em memória. Caso esse objeto não seja acessado durante o tempo de expiração, o mesmo é destruído. Este recurso é essencial quando se usa a estratégia Client-Dependent Instance, eliminando objetos alocados por um cliente quando estes não estão sendo utilizados. O último mecanismo de gerenciamento de recursos é chamado de Passivation (VÖLTER; 2.2. PADRÕES DE PROJETO DE MIDDLEWARE E NUVEM 35 KIRCHER; ZDUN, 2005) e consiste no armazenamento permanente de um objeto seguido da desalocação do estado da memória. Este recurso é útil ao utilizar uma Static Instance, para liberar a utilização de memória nos casos desses objetos estarem sendo pouco acessados. A Tabela 2.1 mostra a relação entre as três classificações de Remote Objectse os mecanismos de ciclo de vida que podem ser utilizados por cada um: Tabela 2.1: Relações entre classes de Remote Objectse mecanismos de gerenciamento de recursos Static Instance Lazy Acquistion útil Pooling inútil Leasing pouco útil Passivation pouco útil Per-Request Intance implicitamente útil muito útil inútil inútil Client-Dependent Instance implicitamente útil pouco útil muito útil muito útil O Broker utiliza um componente específico para lidar com o gerenciamento de ciclo de vida, chamado Lifecycle Manager (VÖLTER; KIRCHER; ZDUN, 2005). Este componente é responsável por criar e gerenciar Remote Objectse utilizar, de acordo com a sua categoria, os mecanismos de gerenciamento de recurso adequados. Adicionalmente, o Lifecycle Manager pode prover uma série de callbacks para que a aplicação execute ações específicas durante algumas etapas do ciclo de vida. 2.2.1.3 Serviços comuns Um middleware DOC dispõe de vários serviços que podem ser utilizados para tratar de requisitos de qualidade, como transparência de localização, tolerância à falhas e monitoramento de qualidade de serviço. Três padrões de projeto podem ser usados com essa finalidade, Lookup e Location Forwarding e QOS Observer. Uma das vantagens principais de middlewares DOC é a transparência de localização, onde um cliente pode acessar um Remote Object sem definir exatamente a localização. O serviço de Lookup é usado justamente para esta finalidade: ele utiliza uma estrutura de dados que é usada para armazenar a localização de objetos em diferentes servidores. Cada Remote Object possui um identificador lógico único no middleware, este chamado de Absolute Object Reference (AOR), que é vinculado a dados de localização pelo serviço de Lookup. A partir desse identificador, o serviço de Proxy consegue descobrir a localização exata de um Remote Object em uma rede. Sem esse identificador lógico, o cliente precisaria informar dados de localização daquele objeto, como IP e porta (como na pilha de protocolos TCP/IP) (VÖLTER; KIRCHER; ZDUN, 2005). O Serviço de Lookup possui pelo menos três primitivas, como pode ser visto na Listagem 2.1: Listagem 2.1: Interface de Serviço de Lookup p u b l i c i n t e r f a c e Lookup { 2.2. PADRÕES DE PROJETO DE MIDDLEWARE E NUVEM 36 void r e g i s t e r ( A b s o l u t e O b j e c t R e f e r e n c e aor , Endpoint endpoint ) ; void u n r e g i s t e r ( AbsoluteObjectReference aor ) ; Endpoint find ( AbsoluteObjectReference aor ) ; } A primeira primitiva, chamada register, é utilizada para vincular um AOR a um endereço de rede, chamado endpoint, que representa a localização física do objeto na rede. A segunda, unregister é utilizada para retirar um AOR do serviço de Lookup. A primitiva find consiste na utilização de uma AOR para obter a localização física (endpoint) de um objeto remoto. Obtendo essa informação é possível construir um Proxy que faça referência a um Remote Object correspondente (BUSCHMANN; HENNEY; SCHMIDT, 2007). Será necessário para o cliente a localização física do serviço de Lookup. O processo de obtenção dessa localização é chamado de bootstrapping. O bootstrapping pode ser resolvido de várias formas, seja fornecendo manualmente as informações de localização ou mais elaborada, através de um broadcast (KIRCHER; JAIN, 2004). Além da transparência de localização, é importante garantir que um Remote Object esteja sempre disponível mesmo que um processo servidor falhe temporariamente. Isso pode ser realizado a partir da utilização de várias réplicas do mesmo objeto em diferentes servidores. Esta estratégia é útil não somente para evitar a indisponibilidade, mas também para distribuir a carga de requisições de maneira eficiente entre todas as réplicas. O padrão de projeto Location Forwarder (VÖLTER; KIRCHER; ZDUN, 2005) pode ser utilizado para esta finalidade. Este pode ser concebido como um protocolo onde o cliente recebe uma mensagem de redirecionamento e procura a nova réplica de objeto remoto, ou como um componente que se encarrega de enviar requisições para a réplica adequada, agindo como um intermediário entre o cliente e o objeto remoto. A vantagem da primeira abordagem é a descentralização dos mecanismos de redirecionamento. A desvantagem é que a concepção de um protocolo de redirecionamento pode ser complexo, e o middleware não possui controle total da distribuição de carga entre as várias réplicas. A segunda abordagem, de se utilizar o Location Forwarder como um componente, é a possibilidade de se utilizar várias abordagens complexas de balanceamento de carga; a desvantagem desta abordagem é presença de um ponto único de falha, em caso de indisponibilidade deste componente. Além do mecanismo de redirecionamento de requisições, pode ser usado um protocolo de gerenciamento de grupos para gerenciar todas as réplicas existentes de um Remote Object. O padrão de projeto Object Group (MAFFEIS et al., 1996) é utilizado para esta finalidade: este define um protocolo onde um Broker pode registrar uma réplica específica em um grupo. O Object Group substitui um AOR de um Remote Object em um serviço de Lookup: ao invés de localizar cada objeto individualmente, o serviço de Proxy passa a registrar a referência de um 2.2. PADRÕES DE PROJETO DE MIDDLEWARE E NUVEM 37 grupo. Requisições destinadas a este Object Group são redirecionada a algum dos membros registrados ou a todos. Um componente de Location Forwarding poderia ser utilizado nesse aspecto, provendo mecanismos eficientes de balanceamento de carga. O protocolo utilizado por um Object Group é dividido em gerenciamento de membros, gerenciamento de view e compartilhamento de estado. O gerenciamento de grupos é realizado a partir das primitivas create_group, destroy_group, join e leave, que permitem, respectivamente, a criação de um Object Group, sua destruição, a entrada de um membro e a saída deste. Uma view é uma representação do estado atual de um Object Group, e contém uma referência para cada membro. Quando um novo membro se junta ou deixa um Object Group, todos os membros existentes recebem uma nova view, indicando quais são os participantes. Cada membro da view é identificada de forma única, e este recurso de identidade pode ser utilizado para selecionar um coordenador do Object Group. As primitivas get_state e set_state são utilizadas para compartilhar o estado de um Remote Object entre todos os membros de um Object Group. A primitiva get_state é utilizado por um dos membros do Object Group para compartilhar o estado atual do objeto. A primitiva set_state é utilizada para os novos membros do grupo, que obterão o estado atual das réplicas. As primitivas de compartilhamento de estados são particularmente úteis para efetuar a migração de um Remote Object de uma localização para outra. A Listagem 2.2 ilustra as primitivas de comunicação de um Object Group agrupadas em uma interface de uma linguagem oritentada a objeto: Listagem 2.2: Primitivas de comunicação do padrão Object Group c l a s s GroupBOA : v i r t u a l p u b l i c BOA { s t a t i c v o i d c r e a t e _ g r o u p ( O b j e c t _ p t r group , c o n s t P r o t o c o l P o l i c y& p o l i c y =default_potocol_policy ); void j o i n ( O b j e c t _ p t r group ) ; void l e a v e ( O b j e c t _ p t r group ) ; s t a t i c void de st ro y_ g ro up ( O b j e c t _ p t r group ) ; v i r t u a l v o i d g e t _ s t a t e ( AnySeq& s t a t e , B o o l e a n& done ) ; v i r t u a l v o i d s e t _ s t a t e ( c o n s t AnySeq& s t a t e , B o o l e a n& done ) ; v i r t u a l v o i d v i e w _ c h a n g e ( c o n s t View& newView ) ; } A qualidade de serviço apresentada por um middleware orientado a objetos deve ser 2.2. PADRÕES DE PROJETO DE MIDDLEWARE E NUVEM 38 Figura 2.6: Relacionamento entre padrões de projeto para serviços comuns de um middleware DOC monitorada. Entre os itens que podem ser monitorados estão o Server Request Handler, o Invoker e cada Remote Object individualmente. O padrão de projeto QOS Observer (VÖLTER; KIRCHER; ZDUN, 2005) é usado justamente para esta finalidade, coletar métricas específicas de cada componente do middleware orientado a objetos. Para que o QOS Observer seja utilizado corretamente, o desenvolvedor do middleware deve prover um gancho específico para cada componente a ser medido. Este gancho deve funcionar de forma semelhante àquela encontrada no padrão de projeto Observer (GAMMA et al., 1993), onde é criado um Subject para cada gancho, que por sua vez registra vários QOS Observers. Quando acontece uma mudança de estado no Subject, este envia uma notificação a todos os QOS Observers registrados. Cada QOS Observer , por sua vez, consulta o estado do Subject e coleta uma série de métricas, como tamanho da mensagem, tempo de execução e quantidade de invocações (VÖLTER; KIRCHER; ZDUN, 2005). A figura 2.6 ilustra os serviços comuns abordados nesta seção, e seu relacionamento. Verificamos que o serviço de Proxy pode registrar uma referencia a um Object Group e este pode usar um Location Forwarder para distribuir requisições entre várias réplicas de um mesmo Remote Object . Também observamos quais componentes de um middleware DOC podem ser monitorados por QOS Observers. 2.2. PADRÕES DE PROJETO DE MIDDLEWARE E NUVEM 2.2.2 39 Arquitetura e Padrões de Projeto para Computação em Nuvem Aplicações desenvolvidas para o ambiente de computação em nuvem possuem diferenças arquiteturais fundamentais. Elas são particionadas e executadas em vários nós, ao invés de um único grande máquina física. Devem ser possível adicionar ou remover recursos computacionais com facilidade e continuar funcionando corretamente quando este fato acontece. Utilizam comunicação assíncrona e uma arquitetura fracamente acoplada. São constantemente monitoradas mesmo quando nós são descartados. Conceitualmente, um nó representa uma unidade lógica de um sistema, que possui recursos de hardware. A lógica de aplicações é executada em nós computacionais e seus dados armazenados em nós de dados. Um nó pode ser representado por uma máquina física, uma máquina virtual ou um cluster de várias máquinas. Em nuvens IaaS, nós representam máquinas virtuais (WILDER, 2012). Um dos requisitos não funcionais que aplicações em ambiente de nuvem necessitam é escalabilidade, que pode ser dividida em dois tipos não mutuamente exclusivos: escalabilidade vertical ou escalabilidade horizontal. A escalabilidade vertical trata do aumento da capacidade de nós existentes, enquanto a horizontal se refere a adição de novos nós à infraestrutura da aplicação. Escalabilidade é tanto uma necessidade de aplicações transacionais, que lidam com acessos de milhares de usuários simultaneamente, mas também de aplicações analíticas que precisam lidar com grandes volumes de dados em tempo real (REESE, 2009). Uma das vantagens de um ambiente de nuvem é a ilusão de escalabilidade infinita decorrente da elasticidade, sobretudo em nuvens públicas. No entanto, não é possível tirar proveito desta escalabilidade se a arquitetura da aplicação não é inerentemente escalável (VARIA, 2010). A contenção de recursos em uma aplicação pode limitar a sua capacidade de alcançar a escalabilidade, gerando gargalos em pontos específicos como acesso a dados ou conexão de rede (WILDER, 2012). A arquitetura de aplicação nativa de nuvem também deve ser projetada para lidar com falhas. Uma máquina virtual pode se tornar indisponível após receber uma grande carga de acessos, os dados armazenados em um nó podem ser perdidos, o balanceador de carga pode falhar, um mestre numa configuração mestre-escravo pode falhar. A melhor maneira de lidar com falhas de infraestrutura é tornar a próprio software resiliente (VARIA, 2010). A tabela 2.2 exibe uma série de cenários onde a falha em um nó pode ocasionar na falha da aplicação. A falha em um nó pode ser causada por um problema de hardware (infraestrutura física), alguma operação interna do provedor ou alguma solicitação do administrador da aplicação. A melhor estratégia para lidar com este cenário é assumir sempre o pior caso, onde o nó será perdido e os dados locais também. Se um único nó pode falhar, devem haver diversas réplicas redundantes de um mesmo nó. Este também não poderá armazenar dados localmente. A aplicação não deve parar de funcionar por conta da falha de um nó. Caso exista a necessidade de 2.2. PADRÕES DE PROJETO DE MIDDLEWARE E NUVEM 40 Tabela 2.2: Cenários possíveis para falha de um nó e o impacto causado (WILDER, 2012) Cenário Falha súbita + reinicialização Desligamento de nó + reinicialização Desligamento de nó + reinicialização Desligamento de nó + terminação Alerta Impacto Prévio Dados locais são Falha súbita de hardware Não perdidos Provedor de nuvem (substituição de Dados locais podem Sim hardware, atualização de software) estar disponíveis Aplicação (atualização, bug e Dados locais Sim reinicialização gerenciada) estão disponíveis Dados locais Aplicação (destruição de um nó) Sim estão perdidos Iniciado Por manter estado na aplicação, este estado deve ser compartilhado com os outros nós, através da utilização de um serviço de armazenamento compartilhado (WILDER, 2012). Deve ser possível iniciar aplicações em nuvem com o mínimo de esforço, automatizando o processo de iniciação e implantação. Isso pode ser realizado através da criação de imagens e de scripts de inicialização. Deve ser realizado monitoramento constante dos recursos utilizados pela aplicação, a fim de obter métricas que representem a qualidade de serviço da aplicação. Por fim, é necessário definir uma estratégia para automatizar a inicialização de novos nós da aplicação seja com base em carga de trabalho, sazonalidade ou algum outro fator influenciado pela qualidade de serviço (VARIA, 2010) (WILDER, 2012) (BALIGA et al., 2011) (MARSTON et al., 2011). 2.2.2.1 Padrões de projeto para computação em nuvem No trabalho desenvolvido por HOMER et al. (2014), podemos identificar vários padrões de projeto que são relevantes para o desenvolvimento de aplicações em nuvem. Serão citados aqueles que foram utilizados na arquitetura proposta por este trabalho. A partir dos princípios arquiteturais vistos anteriormente, é possível destacar que aplicações executadas em ambiente de nuvem precisam ser particionadas e ter tarefas divididas entre vários nós. No entanto, às vezes é preciso que uma tarefa seja executada unicamente em toda a aplicação distribuída. Para realizar este tipo de operação é necessário coordenar as várias réplicas para que apenas uma seja capaz de executar a tarefa em questão. O padrão de projeto Leader Election (HOMER et al., 2014) é usado para esta finalidade. É escolhido um líder entre os vários processos existentes e este líder é responsável por executar aquela tarefa entre todos os nós existentes. O líder pode ser um processo fixo ou pode ser utilizado um mecanismo de sincronização – como um lock distribuído. Existe a necessidade de monitorar a saúde de todos os nós de uma aplicação de nuvem, para saber se cada um está operando corretamente, visando garantir a disponibilidade da aplicação. O padrão de projeto Health Endpoint Monitoring (HOMER et al., 2014) consiste na utilização de checagens funcionais para os vários nós da aplicação e receber uma indicação de funcionamento 2.3. CLOUD AWARE MIDDLEWARE 41 correto. Existem várias formas de realizar esta checagem, seja utilizando códigos de status ou examinando o conteúdo de respostas para analisar se foi recebida a resposta correta. Deve haver cuidado em como o monitoramento da aplicação pode ser realizado. Se o agente de monitoramento realizar checagens muito frequentes, poderá comprometer o funcionamento da aplicação. O próprio agente de monitoramento pode estar com prolemas, logo, é importante que este faça checagens em seus próprios módulos. esporadicamente. Como falhas são inerentes a uma aplicação em um ambiente computação em nuvem, ao utilizar um serviço, este pode apresentar uma falha total ou temporária. Os padrões de projeto Retry e Circuit Breaker (HOMER et al., 2014) consistem, respectivamente: em um mecanismo para evitar falhas temporárias de serviço através da utilização de um mecanismo onde a requisição realizada pelo cliente é tentada novamente; na utilização de condições que evitam a comunicação com um serviço que está aparentemente em mal funcionamento. Os padrões funcionam de forma complementar, onde o Circuit Breaker evita que a ocorrência de um Retry em um serviço que está aparentemente desabilitado. 2.3 Cloud Aware Middleware O Cloud-Aware Middleware (CaMid) MORAIS; LIBERALQUINO; ROSA (2013) é um trabalho de pesquisa desenvolvido pelo grupo Research Group on Foundations and Applications of Distributed Systems (GFADS) com a finalidade de desenvolver um middleware orientado a objetos que possui mecanismos de gerenciamento de nuvem que funcionassem de forma automática e transparente a uma aplicação. O trabalho desenvolvido por MORAIS; LIBERALQUINO; ROSA (2013) apresenta as seguintes contribuições: uma arquitetura de middleware baseada em camadas de middleware consolidada na literatura (SCHMIDT, 2002); utilizar os serviços de nuvem para aprimorar os mecanismos de distribuição (transparência de localização e acesso, modelo de comunicação); integrar as várias camadas de nuvem verticalmente, como uma camada ortogonal a IaaS, PaaS e SaaS; tornar o gerenciamento da nuvem transparente, como parte dos mecanimsos de distribuição. Os princípios que guiam a arquitetura do CaMid são: cloud-awareness ou ciência de nuvem, a capacidade de monitorar e controlar os recursos disponíveis da aplicação de forma transparente, incluindo virtualização, elasticidade e outros; gerenciamento automático, que é a capacidade de manipular recursos sem intervenção humana direta; suporte a aplicações cliente-servidor multi-camada; transparência de localização e acesso; arquitetura baseada em padrões de projeto consolidados (MORAIS; LIBERALQUINO; ROSA, 2013). A arquitetura do CaMid é divida em três camadas, e serve como um dos componentes de um PaaS , em um ambiente de aplicação em nuvem, como pode ser observado na figura 2.7. 2.3. CLOUD AWARE MIDDLEWARE 42 Figura 2.7: Arquitetura em camadas do CaMid, em uma pilha de serviços de nuvem (MORAIS; LIBERALQUINO; ROSA, 2013) O CaMid implementa a arquitetura de um middleware DOC. A camada de infraestrutura do CaMid serve como uma interface para as APIs de programação em rede do sistema operacional de uma máquina virtual. Ela é composta de dois componentes principais, o Client Request Handler e um Server Request Handler , que encapsulam mecanismos de comunicação, como o estabelecimento de conexões de rede e transmissão de dados. A camada de distribuição provê transparência de acesso à aplicação, fornecendo uma abstração de middleware orientado a objeto, utilizando os componentes Proxy, Requestor, Invoker, Remote Object e Marhsaller. Na camada de serviços o CaMid provê uma série de serviços reusáveis que são utilizados para aprimorar o gerenciamento do sistema como um todo. Seus serviços estão divididos em duas categorias, serviço de nomes e serviço de gerenciamento. O serviço de nomes implementa o padrão de projeto Lookup, enquanto o serviço de gerenciamento é utilizado para promover a ciência de nuvem. Os serviços de gerenciamento providos pelo CaMid foram divididos de acordo com seu contexto. O contexto local consiste em operações locais, requisições, migração de serviços e desempenho. O contexto global inclui todos os nós de um sistema, incluindo aplicações e recursos de infraestrutura. Neste contexto, o serviço de gerenciamento, utilizando a API de gerenciamento de nuvem, nomeada como o componente IaaS Manager, monitora todos os recursos da nuvem, como o número de VMs ativas, sua localização e o desempenho da rede virtual. Dados coletados dos contextos locais e globais são identificados por uma chave, que é composta de um Universally Unique Identifier (UUID), informação de contexto, tipo de recurso, id do recurso e localização. A quantidade de informações obtidas do IaaS Manager depende do provedor. Alguns fornecem informação completa, como máquina virtual, localização na estrutura física, enquanto outros limitam as informações fornecidas, como é o caso de informações de hardware em provedores de nuvem pública. A figura 2.8 representa os componentes de gerenciamento do CaMid e sua interação com as demais camadas. São dois componentes principais de gerenciamento, o Local Manager, para 2.3. CLOUD AWARE MIDDLEWARE 43 Figura 2.8: Arquitetura dos serviços de gerenciamento do CaMid o contexto local e o Global Manager no contexto global. O Local Manager é subdividido em dois outros componentes, o Local Monitor, que monitora os recursos de qualidade da aplicação e o Local Controller que gerencia os recursos internos do nó, como o número de threads ativas e objetos remotos. O Local Manager notifica o Global Manager periodicamente, fornecendo informações locais como métricas de desempenho dos componentes de distribuição e objetos remotos, uso de CPU do sistema virtualizado, entre outros. O Global Manager interage com o IaaS Manager para obter informações adicionais da infraestrutura de nuvem, envia instruções para os Local Managers e podem atualizar informações no contexto de Local Managers. 2.3.1 Local Manager A figura 2.9 ilustra os componentes do Local Manager, que consistem no Monitoring Information Service (MIS) , os Observers e o Local Controller. Os Observers são uma realização do padrão de projeto QOS Observer, e é utilizado para coletar informações de qualidade dos componentes da camada de infraestrutura, camada de distribuição, objetos remotos e sistema operacional virtual. Estes podem ser divididos em System Observers, que coletam informações do sistema operacional, como CPU e memória. É utilizado também para informar inconsistências entre as leituras das apis do IaaS Manager. Os Handler Observers são responsáveis por monitorar as requisições, incluindo as métricas vazão e tempo de resposta de todo o middleware. Os Invoker Observers coletam informações da camada de distribuição, mais precisamente do componente Invoker. Por fim, os Remote Service Observers visam a coleta de métricas dos objetos remotos, como tempo de resposta. O MIS coleta informações dos Observers e registra essas informações em tabelas internas, e usa os componentes da camada de distribuição para enviar e receber informações ao Global Manager. O MIS e os Observers constituem o componente Local 2.4. CONSIDERAÇÕES FINAIS 44 Figura 2.9: Interação do Local Manager com demais camadas do CaMid (MORAIS; LIBERALQUINO; ROSA, 2013) Monitor. O Local Controller executa ações demandadas pelo Global Manager, incluindo a inicialização de objetos remotos, atualização de informações do sistema (localização de nós e desalocação de recursos de IaaS . 2.3.2 Global Manager A arquitetura do Global Manager é ilustrada na figura 2.10. O Global Manager é responsável pelo monitoramento e controle do sistema como um todo. O IaaS Requestor requisita informações da nuvem IaaS, como as máquinas virtuais existentes e informação de monitoramento de cada uma delas, como tamanho da memória, CPU, ferramenta de virtualização utilizada. Da mesma forma que os IaaS Requestors, os Global Managers recebem informações de cada Local Manager específico. Nos dois casos, cada pedaço de informação é coletado por um Observer específico. As informações dos dois componentes são consolidas no Information Processor, combinando as informações obtidas. Essas informações podem servir de insumo para ações que podem ser acionadas através do Global Controller. É responsabilidade do Global Controller suportar a alocação e retirada de máquinas virtuais, replicação dos objetos remotos em novas instâncias de máquinas virtuais e balanceamento de carga. 2.4 Considerações Finais Neste capítulo, foi apresentado o conceito de computação em nuvem, quais suas vantagens a respeito de infraestruturas tradicionais e suas características. Foi realizada uma catego- 2.4. CONSIDERAÇÕES FINAIS 45 Figura 2.10: Interação do Global Manager com demais camadas do CaMid (MORAIS; LIBERALQUINO; ROSA, 2013) rização de cada modelo de oferta de serviço de computação em nuvem – SaaS, PaaS e IaaS – observando as vantagens e desvantagens de cada um e como estes modelos se relacionam. Foi realizada uma revisão dos conceitos de middleware, qual a sua definição e quais modelos de comunicação possíveis, ilustrando uma arquitetura que compreende suas camadas principais – infraestrutura, distribuição, serviços comuns e serviços específicos. O modelo de middleware orientado a objetos (ou middleware DOC) foi analisado e foram descritos os seus componentes principais através de padrões de projeto documentados na literatura, incluindo padrões relativos a gerenciamento de ciclo de vidas de objetos remotos serviços comuns. Observamos algumas caracterísiticas fundamentais de aplicações desenvolvidas para computação em nuvem, onde foi citada a necessidade de utilizar uma arquitetura tolerante a falhas, tornar a aplicação fácil de implantar e utilizar scripts de automação baseados em sazonalidade. Por fim, foram introduzidos os princípios arquiteturais do CaMid, os padrões de projeto que o apóiam e os seus componentes principais. Estes tópicos formam os conceitos básicos necessários para entender a motivação e a proposta deste trabalho, e serão utilizadas para justificar as escolhas tomadas pelo desenvolvimento dos mecanismos de suporte a elasticidade do CaMid, que serão mencionados no próximo capítulo. 46 3 Proposta Construir uma aplicação para nuvem, que possa tirar proveito da elasticidade não é uma tarefa simples. A aplicação deve ser pensada para estar particionada em vários nós diferentes. Deve ser possível adicionar mais nós à infraestrutura facilmente e ter benefícios imediatos na escalabilidade do sistema. A aplicação deve continuar disponível mesmo quando um nó torna-se indisponível, seja esta devido a uma falha acidental ou devido ao desligamento manual solicitado pelo usuário de nuvem. Os vários componentes da aplicação também precisam coordenar suas atividades, saber como escalonar tarefas paralelas e possuir capacidade de se comunicar de forma assíncrona. Caso a aplicação precise manter estado, este deve ser compartilhado entre todos os nós, para evitar que a queda de um ocasione em indisponibilidade dos serviços oferecidos pela aplicação. Esses são os princípios básicos que tornam uma aplicação adequada a um ambiente elástico de computação em nuvem. A arquitetura do CaMid (MORAIS; LIBERALQUINO; ROSA, 2013) prevê o suporte à elasticidade, mas não menciona os componentes ou serviços que oferecem este suporte. Neste capítulo vamos detalhar as extensões realizadas à arquitetura do CaMid para que este possa se beneficiar das vantagens proporcionadas pela elasticidade. O CaMid, acrescido deste conjunto de extensões, será chamado de Elastic Cloud-Aware Middleware (eCaMid). A próxima seção apresenta os princípios que guiaram o desenvolvimento do Elastic Cloud-Aware Middleware (eCaMid). Em seguida iremos definir os requisitos necessários para o suporte à elasticidade. Será proposta uma arquitetura que utilize três mecanismos de suporte à elasticidade: comunicação em grupo, que trata da capacidade de gerenciar um grupo de nós, verificando quais desses nós são membros ativos do grupo, provendo meios eficientes de troca de mensagens entre eles e coordenando a execução de tarefas em um ambiente distribuído; replicação, a capacidade de criar nós redundantes que compartilham estado; e balanceamento de carga, que visa distribuir as requisições de uma aplicação entre as diversas réplicas, evitando a sobrecarga de um nó único. Serão detalhadas também as tecnologias utilizadas para a concepção dos mecanismos de elasticidade e de que forma o middleware pode ser implantado em uma infraestrutura de nuvem. 3.1. MOTIVAÇÃO E OBJETIVOS 3.1 47 Motivação e Objetivos O CaMid (MORAIS; LIBERALQUINO; ROSA, 2013) é um middleware orientado a objetos. Logo, seu modelo de programação é baseado em objetos remotos que são compostos por outros objetos que se comunicam através de chamadas de método. Objetos podem ou não conter estado e caso possuam, este estado deve ser gerenciado pelo middleware, evitando que objetos sejam armazenados indefinidamente na memória. Objetos e suas réplicas estarão distribuídos entre vários nós e as requisições realizadas pelos clientes podem ser balanceadas entre os nós existentes. Deve ser possível ainda acessar o estado de cada objeto em todos os nós, evitando que a falha de um no ocasione na indisponibilidade na aplicação. A primeira implementação do CaMid (MORAIS; LIBERALQUINO; ROSA, 2013) introduziu vários componentes importantes: Naming Service, Global Manager, Local Manager e as camadas de comunicação e distribuição. O Naming Service e Global Manager, particularmente, são componente centrais do CaMid, por isso, eles devem sempre estar replicados para evitar que alguma falha nestes ocasione na parada completa do middleware. Os componentes de gerenciamento do CaMid, Global Manager e Local Manager coletam informações do ambiente através de Observers, mas a comunicação entre processos do middleware ainda acontece através de chamadas de método remotas. O CaMid deveria intermediar a comunicação entre Subjects (objetos que são monitorados e geram eventos) e Observers, provendo um estilo de comunicação assíncrono, através da troca de mensagens. Deve ser possível enviar mensagens de um componente localizado em um nó a outro presente em outro nó, utilizando um estilo de comunicação Publish/Subscribe. Publishers publicam mensagens através de uma fila, enquanto os Subscribers tratam essas mensagens. Este estilo de comunicação também pode ser utilizado pela aplicação, que pode combinar o estilo de troca de mensagens com à chamada de métodos de objetos remotos. Os componentes de gerenciamento do CaMid também precisam executar tarefas em intervalos periódicos. Os System Observers, componentes do Local Manager no CaMid responsáveis por captar informações de utilização de CPU e memória, dependem de agentes que obtêm informações periodicamente do sistema operacional. Os Observers do Global Manager também dependem de agentes que obtém informações do IaaS Requestor periodicamente. Estes componentes estarão dispersos em vários nós, portanto as tarefas desempenhadas por estes agentes devem ser coordenadas. Essas tarefas podem ser executadas localmente em cada nó, ou devem ser executadas uma vez para um grupo de nós. As aplicações também devem poder utilizar este recurso, implementando seus próprios agentes. Estes mecanismos do CaMid precisam ser aprimorados para tomar vantagem da elasticidade. No capítulo anterior, foram citadas algumas características fundamentais que uma aplicação distribuída precisa ter para que tome vantagem do paradigma de computação em nuvem: particionamento em múltiplos nós; capacidade de adicionar ou remover nós dinamicamente; preservação do comportamento da aplicação em caso de falha de um nó; modelo de comunicação 3.2. REQUISITOS 48 escalável e fracamente acoplado sem contenção de recursos. Por isso, o eCaMid estende a arquitetura original, visando cumprir os seguintes objetivos: 3.2 Aprimorar os mecanismos de coordenação entre os nós existentes, sabendo quais objetos foram publicados em cada nó e quando um nó está ativo ou inativo. Realizar balanceamento de carga entre os nós, de forma que um único nó não seja sobrecarregado. Preservar o estado de objetos entre os nós, mesmo em decorrência de falha dos mesmos. Utilizar mecanismos de comunicação entre os componentes do middleware que seja assíncrono e funcione independentemente da dimensão atual da infraestrutura do middleware. Agendar e distribuir tarefas periódicas entre os vários nós distintos, independentes de sua dimensão. Requisitos A partir dos objetivos mencionados na seção anterior, foram identificados os seguintes requisitos para o eCaMid: Gerenciar réplicas de nós: O eCaMid poderá adicionar vários nós à sua infraestrutura, onde existem várias réplicas de um mesmo nó. Cada réplica será identificada individualmente e monitorada, para saber que réplicas estão ativas em um dado instante; Gerenciar estado de objetos remotos: o estado dos objetos remotos será compartilhado entre vários nós. O eCaMid deve prover um serviço que permita acessar o estado a partir de qualquer nó; Gerenciar ciclo de vida de objetos: objetos com estado devem ser gerenciados pelo middleware. As estratégias de gerenciamento de ciclo de vida devem levar em conta a distribuição do objeto em diferentes nós; Efetuar comunicação Publish/Subscribe: componentes e objetos do eCaMid poderão trocar mensagens, onde emissores publicam mensagens que são recebidas pelos receptores interessados; Escalonar tarefas: Agentes podem ser usados para implementar ações periódicas, que podem ser executadas para cada nó existente do middleware ou para todos os nós; e 3.3. MODELO DE DOMÍNIO GERAL 49 Realizar balanceamento de carga: requisições encaminhadas para objetos remotos devem ser distribuídas entre todos os nós existentes. É possível identificar quatro atores que interagem com o eCaMid, a aplicação cliente, a aplicação servidor, o provedor de nuvem e uma ou mais máquinas virtuais. A aplicação cliente, que será mencionada apenas como cliente. O cliente conhece as interfaces dos objetos publicados na parte servidor do eCaMid e realiza requisições remotas para esses objetos. A aplicação servidor define os objetos remotos, subscribers e tarefas que serão gerenciados pelo eCaMid. O Provedor de nuvem fornece uma API que é usada pelo componente Global Manager para monitorar as máquinas virtuais existentes e os nós. As máquinas virtuais provêm o ambiente em que processos do eCaMid serão executados. Cada máquina virtual identificada pelo provedor de nuvem deverá possuir pelo menos um endereço de rede. Três tipos possíveis de Stakeholders poderão utilizar o eCaMid, desenvolvedores de aplicações, de middleware e provedores de nuvem. Desenvolvedores de aplicações distribuídas utilizarão o modelo de programação oferecido pelo middleware para desenvolver soluções específicas para o ambiente de computação em nuvem. Desenvolvedores de middleware poderão manter, atualizar as funcionalidades fornecidas pelo eCaMid e propor novas estensões. Provedores de nuvem poderão utilizar o eCaMid como blocos básicos para a criação de serviços de PaaS sobre uma infraestrutura de IaaS. O eCaMid também apresenta os seguintes requisitos não funcionais: 3.3 Independência de provedor de Infraestrutura de Nuvem: Os serviços funcionais do eCaMid que suportam a elasticidade não devem depender de serviços fornecidos por um provedor específico, seja este um provedor público ou privado; Desempenho: O eCaMid deve fazer uso de todas as máquinas virtuais fornecidas pelo provedor de nuvem com eficiência. O uso dos mecanismos de suporte à elasticidade do middleware devem utilizar os recursos da nuvem de forma mais eficiente; Estrutura baseada em padrões de projeto: As soluções implementadas pelo eCaMid devem fazer uso de vários padrões arquiteturais e de projeto presentes na literatura para resolver problemas já conhecidos, de forma a minimizar as complexidades acidentais que são próprias de sistemas distribuídos. Modelo de domínio geral Nas duas últimas seções, pudemos identificar os objetivos e requisitos do middleware. No entanto, para facilitar a compreensão da arquitetura do eCaMid, podemos ilustrar os elementos que compõem o domínio do problema que o middleware pretende resolver, assim como os relacionamentos entre esses elementos. A figura 3.1 ilustra o modelo inicial deste domínio, que será explicado a seguir. 3.3. MODELO DE DOMÍNIO GERAL 50 Figura 3.1: Elementos básicos do modelo de domínio do eCaMid O Provedor de Nuvem fornece uma API para gerência dos serviços de nuvem e um conjunto de Máquinas Virtuais. As Máquinas Virtuais são identificadas unicamente para o provedor de nuvem, e possuem um endereço IP único que pode ser alcançado pelo cliente. Um processo do eCaMid que é executado sobre uma máquina virtual é chamado de Nó. Vários nós compõem um conjunto chamado de Cluster, que por sua vez monitora as máquinas virtuais fornecidas pelo provedor de nuvem através de sua API. Cada nó é identificado de forma única no cluster. Uma Aplicação é um conjunto de vários Componentes agrupados em uma unidade específica. A aplicação é implantada em um cluster, que por sua vez gerencia todos os componentes da aplicação. Um componente é um objeto administrado pelo middleware, e pode ser realizado como: uma Tarefa que é executada periodicamente; um Observer que trata eventos oriundos da aplicação ou do próprio middleware; e um conjunto de Objetos Remotos. Todos os componentes podem possuir objetos remotos como dependência, mas o mesmo não é possível com as outras duas especializações. Um nó é responsável por executar a representação física de um componente em algum instante onde este está sendo utilizado. Um Cliente localiza objetos remotos através do cluster ou do próprio nó, e utiliza a invocação de métodos remotos para fazer requisições a um objeto remoto. Todos esses elementos, com exceção de Tarefa e Cluster já estavam presentes no middleware original MORAIS; LIBERALQUINO; ROSA (2013). Os elementos definidos nesta seção constituem apenas os elementos mais básicos do modelo. Ao longo das próximas seções, novos elementos serão introduzidos ao modelo, ao passo que as funcionalidades do eCaMid serão detalhadas. 3.4. ARQUITETURA 3.4 51 Arquitetura A Figura 3.2 representa os elementos que compõem o eCaMid. Da mesma forma que a implementação inicial do CaMid, a arquitetura do eCaMid é dividida em três camadas: infraestrutura, distribuição e serviços. Alguns novos componentes e serviços foram adicionados à arquitetura. Na camada de infraestrutura, foi adicionado o Group Communication Framework, Cluster Request Handler e Group Channel. Na camada de distribuição, foram adicionados o Cluster Event Bus, Task Scheduler, Invocation Router e Lifecycle Manager. Além dos componentes mencionados, foram adicionados os serviços Load Balancing Service e Storage Service na camada de serviços. Os componentes Server Request Handler, Client Request Handler, Requestor, Invoker, Management Service e Naming Service já existiam na implementação original (MORAIS; LIBERALQUINO; ROSA, 2013). Figura 3.2: Visão geral dos componentes do eCaMid. Os elementos de cor branca representam componentes, os de cor cinza representam serviços, enquanto o elemento preto representa um framework. Os elementos em tracejado são oriundos da arquitetura do CaMid, enquantos os elementos em linha contínua foram adicionados ao eCaMid. O Group Communication Framework é o componente fundamental dos mecanimos de coordenação e responsável por estabelecer um cluster, localizar e identificar membros (nós) e prover mecanismos de comunicação multicast. O Group Channel e Cluster Request Handler são dois componentes da camada de infraestrutura responsáveis por enviar e receber mensagens 3.4. ARQUITETURA 52 multicast. Os componentes Task Scheduler e Cluster Event Bus utilizam o Group Communication Framework para prover serviços de coordenação em nível mais alto. O componente Lifecycle Manager é responsável por controlar a criação e destruição de objetos. Para isto, ele utiliza o Storage Service para armazenar os objetos remotos e um conjunto de estratégias para gerenciar o estado dos objetos remotos. O Storage service, por sua vez, é uma abstração para um sistema de armazenamento chave-valor que suporta controle de transação e tratamento de eventos. É possível acessar o Storage Service a partir de qualquer um dos nós do middleware. O componentes Lifecycle Manager e Storage Service constituem os mecanismos de compartilhamento de estado utilizados pelo eCaMid. O componente Invocation Router é utilizado na camada de distribuição para distribuir requisições de objetos remotos aos diversos nós de um cluster. Este componente utiliza o Load Balancing Service para definir como a carga de requisições será distribuída. O Load Balancing Service é um componente que define uma série de políticas de balanceamento de carga. Esses componentes utilizam as facilidades providas pelo framework de comunicação em grupo para distribuir requisições recebidas dos clientes. 3.4.1 Coordenação O eCaMid funciona como uma série de nós agrupados em uma entidade lógica denominada cluster. Este cluster precisa de meios eficientes para troca de mensagens entre nós, utilizando diferentes estratégias de comunicação, como um-para-um, um-para-muitos e muitospara-um. Também precisa ter a capacidade para verificar que membros estão ativos, quando um novo nó é adicionado ou quando um nó deixa o grupo, com a capacidade de executar ações específicas quando algum desses eventos acontece. O gerenciamento de membros do eCaMid é realizado através da utilização do framework de comunicação em grupo. Este framework utiliza o padrão de projeto Object Group (MAFFEIS et al., 1996), mas ao invés de gerenciar réplicas de objetos remotos, este gerencia nós de um cluster. Cada membro do cluster recebe um identificador. O conjunto de todos os membros ativos do cluster compõem uma View. Quando algum membro entra ou sai do grupo, uma nova View é gerada. O framework de comunicação em grupo provê uma série de gatilhos para execução de ações quando determinados eventos ocorrem no cluster, como a geração de uma view ou a falha de comunicação de um dos membros do nó. Algumas ações precisam ser executadas de forma única em todo o cluster. O padrão de projeto Leader Election (HOMER et al., 2014) define um processo que é utilizado para determinar um líder, o membro do cluster que realizará uma determinada tarefa em favor de todos os outros membros. O eCaMid utiliza o evento de aquisição da view para executar uma ação de atribuição de papéis específicos a cada nó. Um desses papéis é chamado de coordenador, um papel atribuído pelo próprio framework de comunicação em grupo. O coordenador é o membro mais antigo do cluster e é responsável 3.4. ARQUITETURA 53 por executar tarefas específicas para o próprio framework. Os demais membros do cluster são chamados workers e são responsáveis por receber chamadas de método remotas. Um outro papel definido é o Task Executor, que define um nó responsável por gerenciar os agentes que executarão tarefas periódicas no cluster. Além dos mecanismos de gerência de grupo, o eCaMid possui dois componentes que oferecem uma infraestrutura alternativa que pode ser usada para comunicação intra-cluster. Enquanto o Client Request Handler e Server Request Handler são usados na comunicação cliente-servidor, o Group Channel é usado para enviar mensagens a outros membros do grupo, utilizando o identificador do nó ao invés do endereço de rede. O Group Channel suporta o estilo de comunicação unicast (um para um, com semântica request-reply) e multicast (um para muitos, com semântica fire-and-forget). O Cluster Request Handler é o componente de infraestrutura que recebe mensagens do Group Channel e as encaminha para outros componentes da camada de distribuição, como o Invoker e Cluster Event Bus. O Group Communication Framework age como um intermediário entre esses dois componentes. A Figura 3.3 ilustra este estilo de comunicação. Figura 3.3: Estilos de comunicação um-para-um e um-para-muitos 3.4.1.1 Comunicação Publish/subscribe Os componentes Group Channel e Cluster Request Handler são dois componentes fundamentais para a execução de tarefas assíncronas no eCaMid. No entanto, ambos são componentes de baixo nível. Os componentes da camada de serviço e a aplicação necessitam de um modelo de programação mais abstrato. Uma forma de implementar a comunicação assíncrona entre os diversos componentes é através da troca de mensagens. Utilizando um modelo Publish/subscribe, um publisher pode enviar uma mensagem específica sem saber ao certo o destinatário. As mensagens são entregues a todos os subscribers interessados na mesma. A Figura 3.4 mostra os elementos de domínio 3.4. ARQUITETURA 54 deste subsistema. Figura 3.4: Modelo de domínio do subsistema de publish-subscribe No escopo do eCaMid, as mensagens trocadas entre componentes são chamadas de eventos. Eventos podem ter três naturezas: locais, onde o evento publicado por um publisher é entregue para todos subscribers no mesmo nó; eventos de broadcast, onde o evento publicado em um publisher é destinado aos subscribers em todos os nós do middleware; e eventos de cluster, onde o publisher em um nó publica uma mensagem que deve ser entregue a todos os publishers localizados em um dos nós membros do cluster, de forma a balancear a entrega de requisições entre nós. O componente responsável por publicar os eventos e encaminhar aos subscribers interessados chama-se Cluster Event Bus. Este componente é composto de duas partes: o Message Router, responsável por enviar e receber mensagens para os destinatários locais e remotos, encapsulando as chamadas ao Group Channel e o Cluster Request Handler; o Local Event Bus é responsável por entregar os eventos recebidos a todos os subscribers localizados neste nó. A principal finalidade do mecanimso de comunicação Publish-Subscribe é prover um modelo de comunicação para os componentes de monitoramento do eCaMid, pertencentes ao Local Manager e Global Manager que se comuniquem de forma fracamente acoplada e sem contenção de recursos. No entanto, esses mecanismos também estão disponíveis para aplicações que utilizem o eCaMid que desejem utilizar um mecanismo de comunicação assíncrona mais simples, sem todas as garantias e complexidades de um middleware orientado a mensagens. 3.4.1.2 Escalonamento de tarefas periódicas O eCaMid e a aplicação podem necessitar de uma infraestrutura para executar tarefas periódicas. A coordenação e execução dessas tarefas é responsabilidade do componente Task 3.4. ARQUITETURA 55 Figura 3.5: Modelo de domínio do subsistema de escalonamento de tarefas Scheduler. O modelo de domínio para o subsistema de escalonamento de processos é mostrado na Figura 3.5. As tarefas periódicas podem ser classificadas como tarefas locais e tarefas de cluster. Tarefas locais são executadas no contexto de execução de cada um dos nós, enquanto tarefas de cluster são executadas em um nó específico em prol de todo o cluster. Como exemplo de tarefas periódicas locais, temos o processo de extração das métricas de uso de CPU e memória que é executada em cada nó pelo Local Manager. Como exemplo de tarefa de cluster, temos um dos agentes do Cluster Manager que solicita periodicamente do provedor de nuvem o status de todas as máquinas virtuais usadas pelo middleware. O componente Task Scheduler está presente em todos os nós e pode executar qualquer tipo de tarefa periódica. O Task Scheduler recebe eventos relacionados à criação de uma view a partir do Task Coordination Observer. O evento de criação de view informa para o Task Scheduler quais os membros atuais do cluster. Caso o Task Scheduler atual seja o coordenador da view, este será o responsável por executar as tarefas periódicas do cluster. Caso contrário, apenas as tarefas locais são executadas. O Task Scheduler também responde a eventos de desligamento do nó, interrompendo a execução de tarefas locais e de cluster de maneira graciosa. 3.4.2 Compartilhamento de Estado 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 Lookup presente 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. 3.4. ARQUITETURA 56 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 transparentes 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 transparente. 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 ClientDependent 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 Manager utiliza o UUID para guardar um objeto que representa a sessão de um cliente 3.4. ARQUITETURA 57 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 Service pelo 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 ClientDependent Instances inconsistentes é 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 3.4. ARQUITETURA 58 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 Factory solicita 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. 3.4. ARQUITETURA 59 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 mecanismo 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. A Figura 3.9 ilustra os componentes envolvidos pelos mecanismos de balanceamento 3.4. ARQUITETURA 60 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 Strategy e 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 é responsá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 3.4. ARQUITETURA 61 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 Strategy para saber a que nó deverá encaminhar a requisição (2.1); 3.5. TECNOLOGIAS UTILIZADAS 62 5. Se o nó for o mesmo que do Invocation Router, este encaminha a Method Request Message para 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 Message ao 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 simplificar a explicação do processo. 3.5 Tecnologias utilizadas A implementação do eCaMid depende de várias tecnologias para implementar as suas funcionalidades. 3.5. TECNOLOGIAS UTILIZADAS 63 O framework de comunicação em grupo utilizado pelo eCaMid chama-se JGroups. Os componentes Group Channel e o Cluster Request Handler são duas abstrações criadas pelo eCaMid com a finalidade enviar e receber mensagens em um ambiente intra-cluster. A implementação atual do Storage Service utiliza a tecnologia Infinispan (MARCHIONI, 2012) para criar vários repositórios chave-valor distribuídos com finalidades específicas. O Storage Service define um repositório para cada serviço específico do eCaMid. Cada repositório possui configurações específicas: os repositórios do Local Manager e Global Manager utilizam um repositório chave-valor básico; os repositórios do Naming Service e Load Balancing Service são otimizados para leitura de informações, portanto, utilizam um cache L1 provido pelo Infinispan para conservar os dados mais requisitados na memória de cada nó; o repositório utilizado pelo Lifecycle Manager é configurado para descartar os valores armazenados após um tempo de expiração definido, além de utilizar um gerenciador de transações para garantir a consistência da atualização do estado de objetos remotos que é acessado em diversos nós de um cluster. Para fazer a "cola"de seus vários subsistemas, o eCaMid usa em seu núcleo um framework de injeção de dependências chamado Guice (VANBRABANT, 2008). Esta tecnologia fornece um container que é responsável pela criação de cada objeto utilizado no eCaMid e de cada uma de suas dependências. Todos os componentes internos do eCaMid são objetos gerenciados pelo Guice. Os componentes do eCaMid estão agrupados na forma de módulos: existe um módulo com as funcionalidades principais, como invocação de métodos remotos, gerenciamento de ciclo de vida e a API de storage; um módulo com a implementação do Storage Service; um módulo com as funcionalidades de coordenação e clustering, utilizando o JGroups; um módulo com os mecanismos de balanceamento de carga usados no eCaMid; e por fim, um módulo com os serviços de gerenciamento, o Local Manager e Global Manager. A aplicação que usa o eCaMid também utiliza o mecanismo de módulos do Guice para definir quais componentes irão compor a aplicação. O eCaMid provê uma API específica para configuração de um módulo de uma aplicação, permitindo que este defina todos os objetos remotos, a estratégia de ciclo de vida de cada um deles, um conjunto de subscribers e tarefas periódicas. O Lifecycle Manager fornece um conjunto de extensões ao Guice que permite a utilização das estratégias de ciclo de vida de middleware (Per Request Instance e Client Dependent Instance) através dos mecanismos de injeção de dependência. O Guice também permite a utilização de interceptadores e programação orientada a aspectos, permitindo a criação de comportamentos secundários que podem ser aplicados em diferentes contextos da aplicação. Os coletores de métricas de QoS utilizados no eCaMid utilizam interceptadores em métodos específicos dos componentes Server Request Handler e Invoker para calcular o tempo de resposta e o número de vezes que determinado método foi invocado. Adicionalmente, os interceptadores fornecidos pelo Guice poderiam ser usados para implementar mecanismos de segurança e controle de transação. 3.6. IMPLANTAÇÃO 64 Figura 3.13: Diagrama de implantação para nós do eCaMid 3.6 Implantação O eCaMid é distribuído como uma biblioteca. O desenvolvedor da aplicação precisa desenvolver um módulo, onde declara quais são os objetos remotos, tarefas de background e subscribers que serão gerenciados pelo middleware. Um componente chamado eCaMidClusterServer é utilizado para incluir todos os módulos definidos pela aplicação e para iniciar a execução do middleware. A Figura 3.13 ilustra a arquitetura de implantação do eCaMid. Cada nó individual precisa, de alguma forma, descobrir os seus vizinhos e iniciar um cluster, uma etapa conhecida como bootstrapping. A estratégia utilizada pelo eCaMid é definir pelo menos um nó encarregado de centralizar os mecanismos de descoberta dos demais nós. O endereço de rede utilizado por ambas as máquinas virtuais deve ser conhecido previamente. Os nós executados sobre as duas máquinas virtuais devem ser executados em modo de administrador do cluster e os endereços de ambas as máquinas virtuais devem ser passadas como parâmetro. Os dois nós mencionados podem ser categorizados como nós fixos, e são utilizados pelos demais nós para localizar os outros membros do cluster. Foram escolhidos a presença de dois nós, para que o primeiro atue como nó principal e o segundo como failover. Contudo, qualquer número de nós fixos pode ser usado, e o uso de mais de um nó fixo existe para garantir um mecanismo de failover, evitando um ponto central de falha. Caso algum dos nós fixos falhe, é recomendado que o usuário o reinicie com exatamente as mesmas configurações, como endereço IP, para que o cluster não perca a capacidade de bootstrapping. O demais nós do eCaMid são chamados de nós elásticos e podem ser ativados a qualquer 3.7. CONSIDERAÇÕES FINAIS 65 momento pelo usuário. Cada nó elástico precisa saber a localização dos dois nós fixos para então descobrir a localização dos demais membros do cluster. À medida que novos nós elásticos são adicionados à infraestrutura do middleware pelo usuário de nuvem, os novos membros utilizarão uma configuração inicial para localizar os nós fixos e serão adicionados ao cluster dinamicamente. O cliente do eCaMid está implantado em uma máquina virtual separada. Para realizar a ação de bootstrapping, o cliente precisa saber o endereço de rede de um nó fixo para então acessar o serviço de nomes que está implantado em ambos. A partir do serviço de nomes, o cliente obterá a localização de um dos routers, que será o intermediário do cliente para a realização de requisições remotas. 3.7 Considerações Finais Neste capítulo, foram apresentados os objetivos e requisitos da arquitetura do eCaMid. Em seguida, foram explicados todos os mecanismos adicionados à arquitetura do CaMid original: coordenação, comunicação assíncrona, execução de tarefas, compartilhamento de estado, gerência de ciclo de vida e balanceamento de carga. Nas demais seções foram explicadas as tecnologias utilizadas pelo eCaMid para prover seus serviços e uma arquitetura de implantação para o mesmo. 66 4 Avaliação de Desempenho e Discussão No capítulo anterior, foram apresentados vários mecanismos que estendem as funcionalidades fornecidas pelo CaMid original, de forma a suportar o desenvolvimento de aplicações elásticas na nuvem. No entanto, a arquitetura e os mecanismos apresentados precisam ser validados, para que seja possível quantificar os benefícios de desempenho e escalabilidade trazidos pelas novas funcionalidades. Neste capítulo, iremos apresentar uma avaliação experimental que foi realizada com o eCaMid. Iniciaremos este capítulo citando os objetivos da avaliação e a metodologia utilizada. Em seguida, serão mostrados os resultados obtidos a partir da avaliação e será realizada uma análise dos benefícios e prejuízos dos novos mecanismos do eCaMid nos cenários avaliados. 4.1 Objetivos e Metodologia A avaliação experimental usada no eCaMid utiliza a metodologia sistemática definida por JAIN (1991), voltada para avaliação de desempenho. O experimento realizado no eCaMid visa provar que os mecanismos de coordenação, replicação e balanceamento de carga não causam a queda de desempenho da aplicação. É necessário também provar que o mecanismo de balanceamento de carga utilizado consegue preservar o desempenho da aplicação quando nós são adicionados dinamicamente em um cluster, provando que seus mecanismos internos são capazes de reagir a mudanças de topologia rapidamente. Para implementar a avaliação foi desenvolvida uma aplicação simples, que foi desenvolvida utilizando o modelo de programação do eCaMid. Esta aplicação é constituída de um objeto remoto chamado PasswordEncryptionService que contém um método que aplica um hashing criptográfico a uma senha, utilizando o algoritmo PBKDF2WithHmacSha1, com um salt de 64 bits e uma senha de 160 bits. Este algoritmo aplica várias funções de hash à senha utilizada iterativamente, com o objetivo de aumentar o tempo necessário para realizar um ataque de força bruta que visa descobrir a senha original a partir do hash gerado. O objetivo desta aplicação é prover um kernel possa executar uma operação que é exigente em termos de processamento (uso de CPU), é comum em aplicações de nuvem (hashing criptográfico de senha) e não depende de 4.1. OBJETIVOS E METODOLOGIA 67 um mecanismo de persistência durável, como é o caso de um banco de dados. Duas versões do mesmo objeto foram construídas. Na versão stateless, um salt é gerado a cada vez que um método é chamado e é aplicado o hashing criptográfico à senha utilizando este salt e o número de iterações do algoritmo. Na versão stateful, o salt é criado apenas na construção do objeto, permanecendo na memória mesmo a cada execução. Dois diferentes cenários foram utilizados para fazer a avaliação experimental do eCaMid. O primeiro consiste no uso de uma máquina virtual representando a aplicação cliente e uma aplicação servidor com um conjunto de objetos remotos, o serviço de nomes e o global manager, que é executada em uma segunda máquina virtual. Neste primeiro cenário, o middleware é executado sem os mecanismos de suporte à elasticidade fornecidos pelo eCaMid, visando criar um ambiente similar ao utilizado na avaliação experimental do CaMid original. O segundo cenário é bastante similar ao primeiro, com uma máquina virtual contendo o cliente e a outra com a parte servidor. Neste caso, no entanto, os mecanismos de coordenação, compartilhamento de estado e balanceamento de carga foram ativados. Adicionalemente, novos nós seriam adicionados ao cluster em intervalos regulares, através de um script, cada um executado uma nova máquina virtual. Apenas um nó fixo será utilizado, sem a utilização de failover, visto que esta avaliação não procura avaliar os mecanismos de disponibilidade do middleware. Este cenário visa criar um ambiente onde são utilizados os recursos de elasticidade do eCaMid, incluindo a sua capacidade de adaptação ao redimensinamento da infraestrutura. 4.1.1 Métricas, Parâmetros e Fatores As métricas utilizadas para avaliar o desempenho do eCaMid são tempo de resposta e vazão. As métricas tempo de resposta e vazão visam medir o desempenho e escalabilidade do sistema. A fórmula usada para medir o tempo de resposta é: Tresposta = t f im − tinicio , onde t f im representa o instante em que a requisição foi concluída com sucesso e tinicio representa o instante em que a requisição foi iniciada. Para o cálculo do tempo de resposta, apenas as requisições que completaram com sucesso são contabilizadas. A fórmula usada para calcular a vazão é: V = Rsucesso , onde Rsucesso representa o número T de requisições completadas com sucesso e T representa um intervalo temporal específico. A métrica de tempo de resposta é calculada para cada requisição realizada durante a avaliação. Já a métrica de vazão é calculadas uma vez ao final da avaliação, utilizando o número de requisições para um intervalo específico. Uma série de parâmetros podem afetar as métricas mencionadas: (1) Número total de clientes concorrentes em um intervalo X; (2) O número total de iterações utilizado pelo algoritmo PBKDF2WithHmacSha1; (3) Tamanho do salt utilizado; (4) Tamanho do hash gerado; (5) Taxa de transferência da rede; (6) Capacidade de processamento da máquina virtual; (7) Quantidade de servidores virtuais; (8) Estado de objeto remoto. 4.1. OBJETIVOS E METODOLOGIA 68 As aplicações, em ambos os cenários, devem ter a escalabilidade suficiente para atender um grande número de requisições simultâneas. O número de clientes que realizam requisições influenciam diretamente as métricas de tempo de resposta e vazão. O tempo de resposta do sistema avaliado deve apresentar um valor baixo quando o número de clientes é pequeno, e deve crescer à medida que o número de clientes aumenta. A vazão não apresenta o mesmo tipo de variação. Caso o número de clientes seja baixo, a vazão deve apresentar um valor baixo. A vazão do sistema aumenta com um número de clientes até alcançar um ponto de saturação. Após este ponto, a vazão do sistema tende a cair. Este comportamento pode ser provado analiticamente através da teoria das filas (BAKOUCH, 2011). O número de iterações, dos parâmetros que afetam o mecanismo de hashing criptográfico, possui a maior influência sobre as métrica de desempenho, pois este tem um impacto direto sobre a complexidade computacional do algoritmo. Logo, se o número de iterações é grande, maior será o tempo de resposta do sistema e menor a vazão. Pode ser fixado um tamanho de hash e salt entre os valores recomendados enquanto são variados os valores de número de iterações para aumentar ou diminuir o tempo de resposta (TURAN et al., 2010). A taxa de transferência da rede pode influenciar diretamente o desempenho e escalabilidade do sistema avaliado. Por este motivo, para os dois cenários avaliados, é utilizado um ambiente de rede homogêneo. A mesma estratégia é adotada para a capacidade de processamento, utilizando máquinas virtuais com a mesma configuração em todos os cenários avaliados. A quantidade de servidores virtuais usados na avaliação tem pouca influência no desempenho, mas grande influência na escalabilidade do sistema avaliado. No primeiro cenário, um único servidor virtual é utilizado, enquanto no segundo cenário, é utilizado um único servidor virtual e mais quatro servidores virtuais são adicionados através do script que executa o teste de desempenho. Foi escolhido o número total de cinco servidores virtuais para que fosse possível observar o ganho incremental nas métricas ao se adicionar novos servidores virtuais na infraestrutura. Caso o objeto remoto apresentado pelo sistema testado possua estado durante a execução do middleware, este pode afetar de maneira adversa o desempenho do sistema avaliado por conta do esforço necessário para manter este estado consistente. Caso este mesmo objeto seja utilizado concorrentemente, a sincronização dessas requisições adicionam um impacto sobre o desempenho do middleware. Se este estado for compartilhado com outros nós, como é o caso do segundo cenário, o custo de sincronização afetará diretamente o tempo de resposta e vazão da aplicação. Dentre os parâmetros citados, alguns foram escolhidos como fatores do experimento. Foram escolhidos parâmetros que podem ser variados durante a geração da carga de trabalho realizada no experimento e que são pertinentes para ambos os cenários. Os fatores escolhidos, e seus respectivos valores são: Número de clientes: Foram utilizados os valores 50, 100, 150 e 200 para a quantidade de clientes simultâneos. Estes valores são suficientes para testar a aplicação em 4.1. OBJETIVOS E METODOLOGIA 69 cenários diversos. 4.1.2 Número de iterações para o algoritmo PBKDF2WithHmacSha1: Foram selecionados os valores 8000, 16000, 32000 e 64000 iterações para o algoritmo de hashing criptográfico. Estado do objeto remoto: Este fator possui dois níveis: com estado (stateless) e sem estado (stateful). Técnica de avaliação, carga de trabalho e projeto de avaliação Foi escolhida a técnica de experimentação para realizar a avaliação de desempenho do eCaMid. Esta técnica permite testar um protótipo real do middleware, em uma situação que se aproxima do uso real de uma aplicação distribuída. O provedor de nuvem escolhido foi o AWS, onde o serviço Elastic Compute Cloud (EC2) foi utilizado para provisionar as máquinas virtuais que foram usadas nos experimentos e fornecer uma imagem que já continha uma instalação prévia do eCaMid e um script de inicialização. As máquinas virtuais utilizadas em todos os experimentos e cenários eram da classe m1.small, com 1.7 GB de memória RAM e 1 Compute Unit1 e localizadas na zona us-west-2a. Em cada máquina virtual foi instalado o sistema operacional Ubuntu Server 64 bits 12.04. Uma máquina virtual separada foi utilizada para simular os clientes do sistema avaliado. Um programa sintético foi utilizado para simular os clientes, registrar o tempo de resposta de cada requisição e registrar se esta foi terminada com sucesso ou não. Cada cliente é simulado através de uma thread separada, onde cada cliente realiza uma nova requisição, com um intervalo entre cada requisição. O valor deste intervalo é definido como uma variável aleatória distribuído através de uma função gaussiana, com média de 300 ms e desvio padrão de 100 ms. Cada experimento teve uma duração de 12 minutos, onde um minuto é utilizado como tempo de espera para que o programa sintético seja carregado e estabilizado (warm-up). O segundo minuto do experimento é utilizado para iniciar cada cliente em intervalos regulares (ramp-up). Supondo que sejam 200 clientes usados no experimento, então um novo cliente é iniciado a cada 30 segundos. O programa sintético foi criado através da utilização da ferramenta JMeter (APACHE JMETER, 2013). Foi criado um Sampler específico do JMeter que utiliza a parte cliente do eCaMid para se comunicar com a parte servidor da aplicação, onde o cluster está desativado no primeiro cenário e ativado no segundo. Através do JMeter foi possível implementar os mecanismos de simulação de clientes, warm-up e ramp-up utilizados no experimento. Os objetos remotos que contém a função de hashing criptográfico, podem ou não conter estado. Na implementação stateless, um novo valor de salt é gerado para cada nova requisição 11 Compute Unit é equivalente a capacidade de processamento de um processador Opteron, com 1.0 GHz, fabricado em 2007 4.2. RESULTADOS 70 do método de hashing, portanto, duas invocações para aplicação de hashing à mesma senha irão produzir hashes diferentes. Na implementação stateful, o valor do salt é gerado durante a invocação do primeiro método. Invocações susbsequentes para a mesma senha irão gerar o mesmo hash. O valor retornado por objetos stateful é usado para verificar se houve algum erro de consistência. Objetos stateless utilizam a estratégia Per-Request Instance, enquanto objetos stateful Client-Dependent Instance. Ao final de cada experimento, as máquinas virtuais foram reiniciadas e todos as partes da aplicação, cliente ou servidor, foram reiniciados, para reduzir a possibilidade de saturação dos recursos gerenciados pelo sistema operacional da máquina virtual e da própria aplicação. Os experimentos foram conduzidos em horário comercial, para evitar algum problema relacionado à manutenção da infraestrutura do provedor de nuvem. 4.2 Resultados Foram realizados vários experimentos para avaliar todos os fatores e seus níveis em cada cenário específico. Os experimentos foram divididos em grupos, que são nomeados de acordo com o cenário e o tipo de objeto remoto utilizado. O cenário onde é utilizado apenas uma máquina virtual cliente e outra máquina virtual servidor é chamado de "Direct", enquanto o experimento onde novas máquinas virtuais são adicionadas é chamado de "Elastic-Clustered". Este nome é seguido pelo tipo de objeto utilizado, ou seja, Stateless ou Stateful. Desta forma, temos ao todo, quatro grupos de experimentos: Direct-Stateless, Direct-Stateful, Elastic-Clustered-Stateless e Elastic-Clustered-Stateful. 4.2.1 Resultados individuais de cada experimento O primeiro grupo de experimentos, Direct-Stateless, consiste no uso do primeiro cenário, com apenas um único servidor virtual, sem o mecanismo de clustering ativo e um objeto remoto stateless. A Tabela 4.1 mostra os valores de tempo de resposta para o primeiro cenário (um cliente e um único servidor), utilizando um objeto stateless. Podemos observar que o tempo de resposta sofre grande influência do número de iterações e número de clientes. Fixando o número de iterações e aumentando o número de clientes, podemos verificar um aumento proporcional no tempo de resposta. Se fixarmos em 8000 iterações e comparando ao experimento com 50 clientes, temos um aumento de 111,83% no tempo de resposta ao se utilizar 100 clientes, um aumento de 224,01% para 150 clientes e um aumento de 333,66% para 200 clientes. Ao fixar o número de clientes e aumentar o número de iterações, o tempo de resposta também aumenta. Se fixarmos em 200 clientes, e tomando como base de comparação o experimento com 8000 iterações, temos um aumento no tempo de resposta de 93,40% para 16000 iterações (2x), 271,46% para 32000 iterações (4x) e 609,29% para 64000 iterações. 4.2. RESULTADOS 71 A vazão neste grupo de experimentos é bastante influenciada pelo número de iterações do algoritmo, uma vez que ao fixar o número de clientes e aumentar o número de iterações, é possível verificar uma queda no valor da vazão. Podemos tomar como base o experimento realizado com 100 clientes e 8000 iterações. É possível notar uma queda de 47,59% na vazão ao aumentar o número de iterações para 16000, 73,13% para 32000 iterações e 85,88% para 64000 iterações. Fixando o número de iterações e aumentando o número de clientes, não é possível verificar uma mudança significativa no valor da vazão. Tomando como base o experimento realizado com 16000 iterações e 50 clientes, temos: um aumento de 0,98% na vazão, para 100 clientes; um aumento de 1,50% para 150 clientes; e um aumento de 2,03% para 200 clientes. Este comportamento revela que a vazão pode aumentar de acordo com o número de clientes, mas logo alcança um ponto de saturação, uma vez que um único servidor não pode oferecer uma vazão superior ao valor determinado. Tabela 4.1: Tempo de resposta e vazão para o grupo de experimentos Direct-Stateless Desvio Tempo de Padrão do Vazão Número de Número de Resposta reqs Iterações Tempo de ( s ) Clientes Médio (ms) Resposta 50 8000 1912.48 398.13 21.48 50 16000 3900.64 799.03 11.32 50 32000 7827.18 1595.72 5.85 50 64000 15766.51 3404.48 2.96 100 8000 4051.24 820.81 21.81 100 16000 7994.80 1636.08 11.43 100 32000 15841.15 3454.87 5.86 100 64000 30125.43 7554.98 3.08 150 8000 6196.63 1247.62 21.87 150 16000 12054.57 2538.94 11.49 150 32000 23489.23 5597.71 5.96 150 64000 44718.56 12588.79 3.16 200 8000 8293.75 1703.16 22.02 200 16000 16040.37 3564.74 11.55 200 32000 30808.19 7935.22 6.07 200 64000 58826.57 18205.86 3.21 O grupo de experimentos Direct-Stateful consiste em um conjunto de experimentos realizados utilizando um único servidor virtual, onde um cliente faz chamadas a um objeto remoto stateful. A Tabela 4.2 ilustra as métricas obtidas com a realização deste grupo de experimentos. O tempo de resposta e vazão apresentam comportamento bastante similar àquele verificado ao grupo de experimentos anterior. Fixando um número de iterações em 8000, o tempo de resposta apresenta aumentos de 105,53% para 100 clientes, 215,21% para 150 clientes e 323,76% para 200 clientes, quando comparados ao tempo de resposta do experimento que utiliza apenas 50 clientes. 4.2. RESULTADOS 72 A vazão apresenta comportamento bastante similar ao primeiro experimento, onde diminui à medida que o número de iterações aumenta, mas não apresenta diferença significativa ao aumentar o número de clientes. Fixando o parâmetro de 8000 iterações e aumentando e tomando como base o experimento com 50 clientes, é possível notar um aumento na vazão de 4,56% para 100 clientes, 4,52% para 150 clientes e 0% para 200 clientes. No entanto, o contrário acontece ao aumentar o número de iterações do experimento. Ao fixar o parâmetro de 50 clientes e usando o valor da vazão do experimento para o nível de 8000 iterações como referência, podemos notar uma redução de 45% na vazão ao se comparar com o mesmo experimento utilizando 16000 iterações, 73% comparado ao experimento com 32000 iterações e finalmente redução de 85,58% se comparado ao experimento com 64000 iterações. Os valores da vazão mostram que o desempenho do sistema é fortemente afetado pelo número de iterações utilizados pelo algoritmo, mas a capacidade de servir requisições não se altera conforme são aumentados o número de clientes para 100, 150 e 200. Tabela 4.2: Tempo de resposta e vazão para o grupo de experimentos Direct-Stateful Desvio Tempo de Número de Padrão do Vazão Número de Resposta reqs Iterações Tempo de ( s ) Clientes Médio (ms) Resposta 50 8000 1997.32 683.69 20.59 50 16000 3920.87 740.21 11.26 50 32000 8272.07 1355.26 5.50 50 64000 15695.76 3036.36 2.97 100 8000 4105.07 681.57 21.53 100 16000 8275.17 1087.22 10.73 100 32000 15904.29 3152.28 5.84 100 64000 31440.58 4781.80 2.87 150 8000 6295.79 1007.08 21.52 150 16000 11978.64 1402.58 10.71 150 32000 23275.31 5065.11 5.89 150 64000 44999.69 11665.05 3.11 200 8000 8463.90 918.67 20.59 200 16000 16203.36 3153.84 11.43 200 32000 31837.73 4952.01 5.72 200 64000 58895.39 16956.20 3.17 O terceiro grupo de experimentos, Elastic-Clustered-Stateless, utiliza o segundo cenário (um único servidor virtual, com novos nós adicionados em intervalos regulares de 2 minutos) utilizando objetos stateless. Este grupo de experimento visa mostrar o aumento da vazão resultantes do uso de clustering e balanceamento de carga, em uma infraestrutura dinâmica. A Tabela 4.3 mostra os valores de tempo de resposta, vazão e proporção de erros obtidos durante os experimentos. O tempo de resposta para este grupo de experimentos aumenta à medida que o número de iterações e número de clientes é elevado. Fixando o número de clientes em 50 4.2. RESULTADOS 73 e utilizando como base o experimento em que o número de iterações é igual a 8000, podemos afirmar que o tempo de resposta médio apresenta um aumento de 96,27% para 16000 iterações do algoritmo, 328,92% para 32000 iterações e 673,67%, para 64000 iterações. Fixando-se o número de iterações em 8000, e tomando como base o experimento realizado com 50 clientes, podemos verificar que o tempo de resposta sofre um aumento de 154,91% para 100 clientes, 286% para 150 clientes e 441,57% para 200 clientes. A vazão, assim como nos grupos de experimentos anteriores, apresenta uma queda, conforme o número de iterações é elevado e mantém-se estável caso seja aumentado o número de clientes. Tomando como base o experimento com 8000 iterações e 50 clientes, a vazão apresenta uma redução de 4,67% ao elevar o número de clientes para 100, 1,01% para 150 clientes e 2,03% para 200 clientes. Mantendo-se 50 clientes e tomando-se como base o valor do fator de 8000 iterações, a vazão apresenta redução de 39,64% ao aumentar o número de iterações para 16000, 69,61% para 32000 iterações e 82,46% para 64000 iterações. Da mesma forma que os demais grupos de experimentos, a vazão apresentou pouca variação ao aumentar o número de clientes e apresentou uma redução significativa ao aumentar o número de iterações do algoritmo. Tabela 4.3: Tempo de resposta e vazão para o grupo de experimentos Elastic-Clustered-Stateless Desvio Tempo de Padrão do Vazão Número de Número de Resposta reqs Iterações Tempo de ( s ) Clientes Médio (ms) Resposta 50 8000 692.73 1402.10 47.32 50 16000 1359.65 839.53 28.56 50 32000 2971.23 2473.77 14.38 50 64000 5359.47 2894.16 8.30 100 8000 1765.87 2026.29 45.11 100 16000 2996.27 1538.87 28.58 100 32000 6228.81 5546.95 14.19 100 64000 10687.89 4811.57 8.42 150 8000 2673.91 2464.86 46.84 150 16000 4859.51 3251.26 27.23 150 32000 8779.19 5783.85 15.33 150 64000 15964.65 6466.65 8.35 200 8000 3751.62 2528.46 46.36 200 16000 6442.87 4582.37 27.64 200 32000 12083.41 6798.01 14.73 200 64000 22564.70 11843.50 7.91 O último grupo de experimentos, Elastic-Clustered-Stateful, utiliza o mesmo cenário que o grupo de experimento anterior, mas utilizando um objeto stateful. Os valores de tempo de resposta e vazão para este grupo de experimentos podem ser encontrados na Tabela 4.4. Da mesma forma que os demais grupos de experimentos, o tempo de resposta médio tende a aumentar conforme o número de clientes ou o número de iterações aumenta. Utilizando 4.2. RESULTADOS 74 como referência o experimento com 50 clientes e 8000 iterações, podemos notar um aumento de 118,28% quando é elevado para 100 o número de clientes, 207,36% para 150 clientes e 313,77% para 200 clientes. Com o mesmo experimento de referência, podemos notar um aumento de 93,40% quando o número de iterações é elevado para 100, 207,36% quando elevado para 150 e 313,77% quando elevado para 200 clientes. Esses aumentos percentuais mostram um aumento aproximadamente proporcional no tempo de resposta médio em relação ao número de clientes. A vazão neste grupo de experimentos também é fortemente influenciada pelo número de iterações do algoritmo, mas pouca diferença em relação ao número de clientes. Tomando como base o experimento com 50 clientes e 8000 iterações, podemos notar uma redução de 2,79% na vazão quando o número de clientes é elevado para 100, um aumento de 6,79% quando elevado para 150 clientes e um aumento de 6,84% para 200 clientes. Utilizando o mesmo experimento como referência, a vazão sofre uma redução de 44,62% ao aumentar o número de iterações para 16000, 71,86% para 32000 iterações e 84,89% para 64000 iterações. Tabela 4.4: Tempo de resposta e vazão para o grupo de experimentos Elastic-Clustered-Stateful Desvio Tempo de Padrão do Vazão Número de Número de Resposta reqs Iterações Tempo de ( s ) Clientes Médio (ms) Resposta 50 8000 2095.47 671.43 19.72 50 16000 4052.72 665.77 10.92 50 32000 8231.49 1122.49 5.55 50 64000 15621.19 2988.64 2.98 100 8000 4574.11 850.11 19.17 100 16000 8322.15 1421.50 10.98 100 32000 15930.67 3150.86 5.83 100 64000 28666.47 4133.83 2.90 150 8000 6440.65 1027.45 21.06 150 16000 12957.76 1410.84 10.55 150 32000 23718.77 5258.13 5.87 150 64000 36216.29 5351.00 2.89 200 8000 8670.54 1430.04 21.07 200 16000 16480.27 3196.92 11.24 200 32000 28915.12 4386.49 5.68 200 64000 37511.40 8177.64 3.01 4.2.2 Comparação entre resultados A Figura 4.1 mostra uma série de gráficos de barra que demonstram a diferença entre os valores de tempo de resposta, comparando o número de clientes e o grupo de experimento, para cada valor específico do número de iterações. É possível observar através de todos os gráficos que o tempo de resposta médio do grupo de experimentos Elastic-Clustered-Stateless apresenta 4.2. RESULTADOS 75 o menor valor, comparado aos demias grupos de experimento. O tempo de resposta para os grupos de experimentos Elastic-Clustered-Stateful, DirectStateless e Direct-Stateful apresentam valores similiares nas Figuras 4.1a e 4.1b. No entanto, para níveis maiores do fator número de iterações, podemos observar que o tempo de resposta médio do grupo de experimento Elastic-Clustered-Stateful tende a ser menor quando comparado aos grupos de experimento Direct-Stateless e Direct-Stateful. (a) Tempos de resposta vs número de clientes com (b) Tempos de resposta vs número de clientes com número de iterações igual a 8000 número de iterações igual a 16000 (c) Tempos de resposta vs número de clientes com (d) Tempos de resposta vs número de clientes com número de iterações igual a 32000 número de iterações igual a 64000 Figura 4.1: Gráficos de barra para comparação de tempo de resposta médio entre todos os grupos de experimentos Podemos comprovar esta diferença no tempo de resposta através da comparação dos valores de tempo de resposta entre o grupo de experimentos Elastic-Clustered-Stateful e os 4.2. RESULTADOS 76 grupos Direct-Stateless e Direct-Stateful. Considerando o tempo de resposta como uma variável aleatória T , que possui uma distribuição não normal. Podemos definir como hipótese nula que T1 = T2 , ou como hipótese alternativa que o valor de T1 < T2 , onde T1 corresponde ao tempo de resposta do grupo de experimentos Elastic-Clustered-Stateful e T2 aos tempos de resposta dos experimentos Direct-Stateless e Direct-Stateful. Tabela 4.5: Teste estatístico Mann-Whitney comparando os grupos de experimento Elastic-Clustered-Stateful e Elastic-Clustered-Stateless Número de Clientes 50 50 50 50 100 100 100 100 150 150 150 150 200 200 200 200 Número de Iterações 8000 16000 32000 64000 8000 16000 32000 64000 8000 16000 32000 64000 8000 16000 32000 64000 U P-Value 91278977 24948474 6066395.5 1261866 91278977 24948474 6066395.5 1261866 91278977 24948474 6066395.5 1261866 91278977 24948474 6066395.5 1261866 1.00 1.00 0.26 1.00e-31 1.00 1.00 0.26 1.00e-31 1.00 1.00 0.26 1.00e-31 1.00 1.00 0.26 1.00e-31 4.2. RESULTADOS 77 Tabela 4.6: Teste estatístico Mann-Whitney comparando os grupos de experimento Elastic-Clustered-Stateful e Elastic-Clustered-Stateful Número de Clientes 50 50 50 50 100 100 100 100 150 150 150 150 200 200 200 200 Número de Iterações 8000 16000 32000 64000 8000 16000 32000 64000 8000 16000 32000 64000 8000 16000 32000 64000 U P-Value 87649073.5 24387313.5 5805891.5 1223735 87649073.5 24387313.5 5805891.5 1223735 87649073.5 24387313.5 5805891.5 1223735 87649073.5 24387313.5 5805891.5 1223735 1.00 1.00 0.08 1.04e-31 1.00 1.00 0.08 1.04e-31 1.00 1.00 0.080 1.04e-31 1.00 1.00 0.08 1.04e-31 Como a variável aleatória T não possui uma distribuição normal, foi aplicado o teste estatístico Mann-Whitney, com nível de significância 0.05. Os valores dos testes estatísticos, que mostram uma comparação dos grupos de experimentos Elastic-Clustered-Stateful e DirectStateless, podem ser encontrados na Tabela 4.5 e a comparação entre os grupos Elastic-ClusteredStateful e Direct-Stateful na Tabela 4.6. O valor U representa o valor do teste estatístico Mann-Whitney. Apenas nos experimentos onde o número de iterações é igual a 64000, pudemos rejeitar a hipótese nula. Para este valor do número de iterações, o tempo de resposta do grupo de experimentos Elastic-Clustered-Stateful é menor. Em todos os outros casos, pudemos observar que a hipótese nula foi aceita. Podemos observar os valores de vazão, de todos os grupos de experimentos, comparados através da Figura 4.2. O grupo de experimentos Elastic-Clustered-Stateless apresentou um valor bastante superior da métrica vazão, para qualquer valor de número de iterações e número de clientes. Já os grupos Elastic-Clustered-Stateful, Direct-Stateless e Direct-Stateful apresentaram valores de vazão bastante semelhantes. 4.2. RESULTADOS 78 (a) Vazão vs número de clientes com número de iterações igual a 8000 (b) Vazão vs número de clientes com número de iterações igual a 16000 (c) Vazão vs número de clientes com número de iterações igual a 32000 (d) Vazão vs número de clientes com número de iterações igual a 64000 Figura 4.2: Gráficos de barra para comparação de vazão entre todos os grupos de experimentos A Figura 4.3 mostra o comportamento do tempo de resposta ao longo do experimento. Foram escolhidos os valores de 50 e 200 para o fator número de clientes e os valores 8000 e 64000 para o fator número de iterações, pois estes representam os maiores e menores níveis de cada fator. Todos os grupos de experimento foram tratados em cada gráfico. 4.2. RESULTADOS 79 (a) Tempo de resposta vs tempo do experimento para os valores de 50 clientes e 8000 iterações (b) Tempo de resposta vs tempo do experimento para os valores de 50 clientes e 64000 iterações (c) Tempo de resposta vs tempo do experimento para os valores de 200 clientes e 8000 iterações (d) Tempo de resposta vs tempo do experimento para os valores de 200 clientes e 64000 iterações Figura 4.3: Tempo de resposta vs tempo do experimento para comparação entre os grupos de experimentos No início do experimento é comum, na fase de ramp-up, apresentar valores de tempo de resposta que aumentam lentamente antes do primeiro minuto. Após a fase de ramp-up, o tempo de resposta tende a aumentar um pouco mais até atingir um ponto de saturação, que ocasiona em um valor estável para o tempo de resposta. Durante o início de alguns experimentos, foi possível observar um pico repentino no tempo de resposta, mas que logo em seguida alcançou os valores de ramp-up comuns. Nos grupos de experimentos Elastic-Clustered-Stateless e Elastic-Clustered-Stateful foram adicionados novos nós nos intervalos de 2, 4, 6 e 8 minutos do tempo do experimento. 4.3. DISCUSSÃO 80 Particularmente no experimento Elastic-Clustered-Stateless, podemos observar picos no tempo de resposta quando são alcançados estes instantes, seguidos por quedas bruscas no tempo de resposta, atingindo um ponto de saturação inferior ao anterior. Ao final de cada experimento do grupo Elastic-Clustered-Stateless, o valor do tempo de resposta deste grupo de experimentos é inferior ao dos demais grupos. Os grupos Direct-Stateless e Direct-Stateful apresentaram um comportamento bastante similar em todos os experimentos, visto que não há muita diferença entre eles. Já o grupo de experimentos Elastic-Clustered-Stateful apresentou comportamento similar as Figuras 4.3a, 4.3b e 4.3c, apresentando um ponto de saturação inferior apenas no gráfico mostrado na Figura 4.3d. 4.3 Discussão Pudemos verificar que o grupo de experimentos Elastic-Clustered-Stateless apresentou o melhor desempenho para todos os valores de número de clientes e número de iterações, no cenário testado. Este comportamento era esperado, pois neste grupo a carga de trabalho do cliente é distribuída entre vários servidores virtuais, utilizando mecanismos eficientes de balanceamento de carga. Foi possível observar também a redução no tempo de resposta proporcionado pela adição de novos nós à infraestrutura durante os experimentos do grupo Elastic-Camid-Stateless, mostrando que os mecanismos de coordenação e balanceamento de carga do eCaMid podem responder rapidamente à adição de novos nós. Contudo, os picos no tempo de resposta que ocorreram nos gráficos 4.3a, 4.3c e 4.3d, mostram o custo de coordenação relacionado à adição de novos nós. No entanto, estes picos, em nenhum dos casos, ocasionaram uma perda significativa do desempenho ao longo do experimento. O grupo de experimentos Elastic-Clustered-Stateful, não apresentou uma melhora significativa nos tempos de resposta, a não ser quando foi utilizado um valor de 64000 para o parâmetro número de iterações. Esta diferença tornou-se mais evidente conforme o número de clientes se aproximava do maior valor, ou seja, 200 clientes. O ganho no tempo de resposta foi ocasionado pelo uso dos mecanismos de balanceamento de carga, visto que o sistema como um todo possuía um ponto de saturação menor para esta métrica. Já a vazão do sistema não foi afetada, mesmo quando foram usados os maiores valores dos parâmetros de número de iterações e números clientes. Contudo, torna-se evidente que o mecanismo de compartilhamento de estado entre os nós tem um grande impacto sobre o desempenho do middleware, especialmente se comparado ao grupo de experimentos Elastic-Clustered-Stateless, uma vez que este grupo apresentou valores menores de tempo de resposta e maiores de vazão em todos os experimentos realizados. Este custo é compensado pela capacidade de manter o estado do sistema acessível a todos os nós conforme estes são adicionados à infraestrutura e ao mesmo tempo evitar que este estado seja perdido em caso de desligamento de um nó. 81 5 Trabalhos Relacionados Neste capítulo, serão explicados os vários trabalhos que estão relacionados ao eCaMid. Serão examinadas as tecnologias usadas pelo eCaMid para prover seus mecanismos de coordenação e compartilhamento de estado. Ao mesmo tempo, discutiremos os vários trabalhos de middleware desenvolvidos nos últimos anos que tem como foco o desenvolvimento e integração e gerenciamento de aplicações no ambiente de computação em nuvem. 5.1 Tecnologias fundamentais usadas pelo ElasticCamid Na capítulo 3, nós citamos algumas tecnologias que são usadas como blocos básicos para os mecanismos de coordenação e compartilhamento de estado do eCaMid: JGroups, que fornece blocos básicos para implementação de comunicação em grupo (MONTRESOR; DAVOLI; BABAOGLU, 2001); e Infinispan, um Datagrid que provê uma API chave-valor para armazenamento de objetos, com suporte a transações, queries, transações, expiração e revogação de dados (MARCHIONI, 2012). 5.1.1 JGroups JGroups (MONTRESOR; DAVOLI; BABAOGLU, 2001) é um toolkit que permite a utilização de comunicação em grupo em uma aplicação distribuída. JGroups implementa o padrão Object Group (MAFFEIS et al., 1996), oferecendo para a aplicação um conjunto de callbacks que são utilizados para implementar operações específicas de comunicação em grupo, como criação de View, compartilhamento de estado, recepção de mensagens e detecção de falhas. Um dos componentes principais fornecidos pelo JGroups, é chamado de JGroups (BAN; BLAGOJEVIC, 2013). Através do JGroups é possível criar uma conexão a um grupo existente, obter o endereço dos membros existentes, incluindo o próprio endereço e enviar mensagens para os demais membros. As callbacks de comunicação de grupo são registradas pela aplicação através do JGroups. O JGroups depende de uma pilha de protocolos que, quando agrupados, oferecem um conjunto de funcionalidades a aplicação. Os primeiros protocolos da pilha do JGroups 5.1. TECNOLOGIAS FUNDAMENTAIS USADAS PELO ELASTICCAMID 82 estão relacionados à camada de transporte da pilha de protocolos TCP/IP, e incluem suporte a TCP e UDP. Logo acima dos protocolos de transporte, existem os protocolos de descoberta de membros, responsáveis por realizar o bootstrapping da comunicação em grupo e detecção de novos membros. Os próximos protocolos da pilha oferecem funcionalidades auxiliares como descoberta de nós indisponíveis, fragmentação e ordenamento de mensagens, garbage collection de mensagens recebidas e outros. Acima destes protocolos auxiliares, estão os serviços de gerenciamento de grupo, que adicionam ou removem membros de um grupo e acionam os callbacks de mudança na View. Acima dos protocolos e JGroups, JGroups também oferecem um conjunto de blocos básicos, que permitem a utilização das seguintes funcionalidades: comunicação request-reply síncrona ou assíncrona com o uso de Futures, com suporte a unicast e multicast; serviços de locking e contador distribuídos; execução de jobs em cluster; e finalmente, tabelas hash distribuídas. Apesar de prover inúmeras funcionalidades, vários recursos do JGroups são bastante complexos, e por isso, de difícil utilização em uma aplicação de mais alto nível. O JGroups é útil como parte da camada infraestrutura de um middleware mais complexo (MONTRESOR; DAVOLI; BABAOGLU, 2001). O eCaMid utiliza o JGroups justamente neste tipo de situação, onde provê abstrações de mais alto nível como objetos remotos, tarefas e subscribers, e criando a "cola"necessária para utilizar o JGroups para seus mecanismos de comunicação e coordenação de nós de forma transparente para a aplicação. 5.1.2 Infinispan Mencionamos no capítulo 3, que o Storage Service do eCaMid utiliza o Infinispan (MARCHIONI, 2012) para criar uma série de repositórios distribuídos que são utilizados pelos componentes Naming Service, Management Services (Local Manager e Global Manager) e Lifecycle Manager. O Infinispan é utilizado por servidores de aplicação como o JBoss Application Server (CHAUDHARY et al., 2014) para prover mecanismos de cache e armazenamento de dados (como sessões HTTP) em memória, em um ambiente distribuído (SURTANI et al., 2014). O Infinispan utiliza o JGroups em sua camada de infraestrutura para prover mecanismos de comunicação Peer-to-Peer (P2P) entre nós de um cluster. A partir desta camada de comunicação, o Infinispan oferece suporte a replicação de dados, transações distribuídas, queries e mecanismos de expiração de dados. O infinispan pode ser executado como um banco de dados distribuído, ou pode ser funcionar de forma embarcada em uma aplicação. O infinispan possui três modos de funcionamento: replicação, invalidação e distribuição. No modo de replicação, toda informação armazenada em um nó é replicada a todos os demais nós de um cluster. Este modo de funcionamento depende da utilização de mecanismos de multicast fornecidos pelo JGroups. A escalabilidade do modo replicação é comprometida à medida que mais nós são adicionados ao cluster Infinispan, visto que o custo de sincronização 5.2. TRABALHOS DE MIDDLEWARE DESENVOLVIDO PARA NUVEM 83 das informações torna-se mais alto. No segundo modo de operação, invalidação, o Infinispan não compartilha o estado com outros nós, mas opera como um cache para um banco de dados externo. Objetos extraídos do banco de dados externo são armazenados localmente na memória de um nó. Caso o objeto seja atualizado no banco de dados, uma mensagem de invalidação é enviada para os nós que armazenam o objeto na memória, que removem o objeto do cache. No modo de distribuição, o Infinispan utiliza uma função de hashing para determinar em que nós uma determinada informação será armazenada. Quando a aplicação armazena um objeto através da API chave-valor, a função de hashing é aplicada a chave. O hash gerado é utilizado para determinar a que segmento o objeto será armazenado. A cada segmento é designado um certo número de nós, chamados de donos. Um dos donos é chamado de dono primário, e os demais são chamados de donos backup. Logo, caso um dono primário torne-se indisponível, um dos donos backup assumirá o lugar de dono primário. Um conjunto de segmentos constituem um espaço espaço de chave. O tamanho do espaço de chave é configurável, mas adota um valor de 100 segmentos por padrão. À medida que novos nós são adicionados ou removidos de um cluster, o Infinispan distribui os nós existentes de forma homogênea entre os segmentos. A função de hashing utilizada para mapear chaves de objetos tende a distribuir de forma igual os objetos entre os segmentos existentes. Isso é possível porque o Infinispan utiliza uma função de hashing consistente, que é comum em implementações de Distributed Hash Tables (DHTs) encontrados na literatura (SHEN; XU, 2008) (GUPTA et al., 2003). O modo distribuído do Infinispan permite que este possa manter a escalabilidade mesmo que milhares de nós sejam adicionados à infraestrutura, visto que o estado de um objeto é replicado apenas para uma fração dos nós do cluster. O eCaMid adota, por padrão, o Infinispan em seu modo distribuído e embarcado, visando simplificar o processo de implantação do mesmo e tornar possível que sejam adicionados milhares de nós à infraestrutura do middleware. 5.2 Trabalhos de Middleware Desenvolvido para Nuvem É possível encontrar na literatura um grande número de trabalhos sobre middleware para computação em nuvem. Estes trabalhos costumam abordar vários temas incluindo: uma arquitetura geral para middleware no contexto de computação em nuvem (ABBADI, 2011a) (ABBADI, 2011b); multi-tenacidade, ou a capacidade de compartilhar uma mesma infraestrutura ou plataforma com múltiplas aplicações (AZEEZ et al., 2010) (KäCHELE; HAUCK, 2013); interoperabilidade, seja por criar uma plataforma interoperável entre múltiplos provedores (MAXIMILIEN et al., 2009) (MERLE; ROUVOY; SEINTURIER, 2011), ou criando meios eficientes de comunicação entre nuvens (AMIN et al., 2012); elasticidade (RANJAN et al., 2010) (JAYARAM, 2013), seja através de mecanismos que suportam a adição dinâmica de recursos à infraestruta de nuvem ou o provisionamento automático de nós; requisitos não funcionais de 5.2. TRABALHOS DE MIDDLEWARE DESENVOLVIDO PARA NUVEM 84 aplicações na nuvem, criando mecanismos de suporte à segurança e confiabilidade (CAMPBELL; MONTANARI; FARIVAR, 2012), tolerância a falhas (BEHL et al., 2012). Nas próximas subseções, serão explicados esses vários trabalhos e seu relacionamento com o eCaMid, discutindo seus pontos em comum e suas diferenças. Será também explorado como o eCaMid pode evoluir com base nos mecanismos apresentados nos mesmos trabalhos. 5.2.1 Arquitetura Geral de Middleware ABBADI (2011b), em seu trabalho, cita que a nuvem pode ser dividida em três camadas: a camada física representa os servidores físicos, sistemas de armazenamento e rede de computadores; a camada virtual consiste nos recursos virtuais que são operam sobre a camada física; por fim, a camada de aplicação contém as aplicações que são hospedadas na nuvem através da camada virtual. Além destas três camadas horizontais, temos verticalmente a camada de armazenamento de dados, rede e servidores. Middleware serve como cola entre estas camadas, provendo serviços de adaptabilidade, resiliência, escalabilidade, disponibilidade e segurança. Quatro elementos definem os objetivos da camada virtual, propriedades do usuário incluem requisitos da camada virtual que devem ser definidos pelo usuário, como características de máquinas virtuais e armazenamento, SLAs, segurança e privacidade. Propriedades da infraestrutura são capacidades definidas pelos arquitetos da solução de nuvem, que compreendem distribuição, redundância, confiabilidade e conectividade. Políticas de infraestrutura definem controles para os operadores da nuvem. Mudanças e Incidentes representam mudanças na configuração da camada virtual. Além desses elementos, ABBADI (2011b) definiu que serviços de middleware da camada virtual devem possuir um conjunto de funções. A primeira, a adaptabilidade, consiste em definir um conjunto de ações em resposta a mudanças de configuração, que podem ser resultados de falhas de componente, realocação e aumento de demanda. Estas ações acionam as capacidades de escalabilidade, que instrui um aumento vertical (mais capacidade para um componente) ou horizontal (mais componentes) na infraestruturavirtual. Parte das ações da função de adaptabilidade ativam a função chamada de arquiteto do sistema, que por sua seleciona uma arquitetura para a adaptação que deve ser realizada, com base na escalabilidade, gerenciamento de processos e redundância. O arquiteto do sistema aciona a função de resiliência, que representa ações de administradores do sistema, fazendo com que a comunicação entre servidores e dispositivos de rede mantenham a comunicação e mesmo em caso de falha. A função de resiliência oferece suporte às funções de confiabilidade, responsável por manter a integridade do sistema evitando que dados ou informações sejam perdidos, e disponibilidade, que possui distribui requisições e oferece caminhos redundantes de comunicação entre os componentes da infraestrutura virtual. Os serviços de middleware na camada de aplicação devem implementar funções semelhantes – adaptabilidade, escalabilidade, resiliência, disponibilidade e confiabilidade –, mas voltadas para o gerenciamento de recursos virtuais (ABBADI, 2011a). Três tipos de middleware 5.2. TRABALHOS DE MIDDLEWARE DESENVOLVIDO PARA NUVEM 85 podem ser usados na camada de aplicação para suportar estas funções. O Server Backend Middleware suporta sistemas de armazenamento em máquinas virtuais dedicadas. O Server Middle-tier Middleware suporta servidores de aplicação e web, que podem ser combinados de diferentes formas, e executados sobre uma mesma ou múltiplas máquinas virtuais. Já o Client Frontend Middleware é responsável por tornar o acesso ao Server Middle-tier Middleware transparente. O eCaMid pode ser classificado como um middleware da camada de aplicação. Sua arquitetura possui uma parte cliente e uma parte servidor, que podem representar, respectivamente, Client Frontend Middleware e o Server Middle-tier Middleware. O eCaMid implementa as funções de resiliência, através do protocolo do Naming Service, disponibilidade, através do Load Balancing Service e Group Communication Framework e confiabilidade através do Storage Service. 5.2.2 Multitenancy Multitenancy é a capacidade de múltiplos tenants fazerem uso do mesmo recurso de forma isolada e independente. No caso de middleware para nuvem, múltiplas aplicações ou módulos podem compartilhar de um mesmo conjunto de máquinas virtuais, ou de um conjunto de nós de um middleware. A implementação atual do eCaMid não possui suporte a multitenancy. O uso de multitenancy, no entanto, beneficiaria este middleware, por oferecer mecanismos de suporte mais granulares à elasticidade. AZEEZ et al. (2010), em seu trabalho, propõe um middleware baseada em SOA para desenvolvimento e execução de serviços e composições utilizando multitenancy. Aplicações em SOA, neste contexto, podem ser divididos em execução, segurança e dados. A parte de execução consiste de vários Web Services e composições dos mesmos em Workflows e Mashups. Dados são armazenados através de bancos de dados e outros sistemas de armazenamento e usados pelos elementos de execução. Segurança pode ser definida através de serviços de autenticação, autorização, não-repudiação e confiabilidade que são ortogonais aos elementos de execução e dados. O middleware proposto por AZEEZ et al. (2010) chama-se WSO2 Carbon. No cerne do middleware, há módulo central, chamado de Core, um motor que é responsável pelo carregamento, linking e execução de componentes de aplicação e gerenciamento do middleware, baseados no padrão Open Service Gateway initiative (OSGi). Web Services das aplicações são disponibilizados como bundles OSGi e gerenciados pelo Core. Um módulo Security disponibiliza para a aplicação serviços de gerenciamento de usuários, autenticação e autorização. O isolamento entre diferentes aplicações é provido através do módulo de Service Execution, que impede que as execuções e dados de cada tenant se mantenham isolados, protegendo-os por exemplo, do uso de código malicioso para alterar o comportamento dos serviços. O módulo Data Access provê uma abstração para acesso a registros e repositórios de dados do Core, incluindo 5.2. TRABALHOS DE MIDDLEWARE DESENVOLVIDO PARA NUVEM 86 localização de serviços. Da mesma forma que o Service Execution o módulo de Data Access provê isolamento de acesso entre diversos tenants. Todos estes módulos são executados sobre um motor de execução chamado de Apache Axis2, que permite a implantação de vários componentes. No trabalho desenvolvido por KäCHELE; HAUCK (2013), foi desenvolvido um middleware com suporte a multitenancy chamado COSCA que usa um modelo de programação inspirado em OSGi. Este middleware introduz um conceito chamado de frameworks virtualizados, que tem a capacidade de mapear um conjunto de bundles em uma aplicação, onde cada aplicação é mantida de forma isolada. Múltiplos frameworks são executados sobre uma mesma Java Virtual Machine (JVM), de forma isolada, em múltiplos classloaders sob a gerência de um security-manager. Cada JVM é executada sobre um servidor físico separado, sem a necessidade de uma intermediação de uma camada de IaaS. O COSCA, desta forma, constitui um PaaS que opera diretamente sobre uma plataforma de hardware. Esta plataforma também mantém um componente chamado Distributed Service Registry, que funciona como um componente central utilizado para registrar serviços de aplicações cadastrados em cada nó, como um serviço de Lookup. Cada JVM mantém um serviço de monitoramento que verifica a utilização decada componente de uma aplicação através da medição do uso de CPU e chamada de serviços. Quando um componente está consumindo uma grande quantidade de recursos, ele é implantado em outro nó, com replicação. Quando uma única JVM está com todos os seus recuros exauridos, um dos componentes da aplicação é migrado para outro nó. A implantação é possível graças a um serviço de provisionamento compatível com OSGi (KäCHELE; HAUCK, 2013). O COSCA, possui algumas limitações quanto acoplamento entre diferentes componentes de uma mesma aplicação (KäCHELE; HAUCK, 2013). Há situações em que estes componentes não podem ser migrados e replicados separadamente. Por isso a estrutura deles é investigada, e caso seja detectado um forte acoplamento entre os mesmos, estes são tratados como um único componente. O middleware também não oferece suporte a compartilhamento de estado, o que limita o potencial de escalabilidade por dificultar a replicação e composição de componentes da aplicação. A estratégia utilizada neste caso é implementar o compartilhamento de estado através de uma base de dados externa, como um banco de dados relacional ou um serviço de coordenação como o Zookeeper (APACHE ZOOKEEPER, 2014). Em ambos os trabalhos foi constante a presença da tecnologia OSGi para implementar mecanismos de modularização e multi-tenacidade. Um subsistema OSGi poderia ser adicionado ao núcleo do eCaMid e definir serviços que garantam a segurança e isolamento de aplicações. Este mecanismo poderia implementado no eCaMid para para oferecer um controle de elasticidade mais granular, onde múltiplas aplicações compartilham do mesmo conjunto de máquinas virtuais. Da mesma forma, o COSCA poderia se beneficiar dos mecanismos de balanceamento de carga e compartilhamento de estado do eCaMid, que tornaria o serviço mais adequado à implantação em máquinas virtuais e não dependeria de mecanismos armazenamento de estado e coordenação externos. 5.2. TRABALHOS DE MIDDLEWARE DESENVOLVIDO PARA NUVEM 5.2.3 87 Interoperabilidade A interoperabilidade, no contexto de computação em nuvem, pode ter dois significados: um mecanismo de comunicação destinado a integrar diferentes aplicações executadas em múltiplas nuvens; uma plataforma que possa ser executada por muitas linguagens de programação, em diversos provedores diferentes de nuvem. O trabalho desenvolvido por AMIN et al. (2012) constitui o primeiro tipo de interoperabilidade. O Intercloud Message Exchange Middleware (ICME) é um middleware que utiliza um padrão de comunicação por troca de mensagens e presença, chamado de Data Distribution Service (DDS), desenvolvido pelo Object Modeling Group (OMG). O serviço DDS depende de um componente chamado de Global Data Space (GDS), que funciona como um ponto central para o registro de tópicos, em um estilo de comunicação Publish/Subscribe, que desacopla os participantes da comunicação. O ICME extende as funcionalidades providas pelo DDS, através da definição de um modelo de informação que reflete um cenário de computação em nuvem. Os participantes do modelo de informação fornecido pelo ICME são chamados de entidade. Um dos tipos de entidade é chamado de Message, que por sua vez pode ser de do tipo Request e Response. A entidade define os tipos possíveis de mensagem é denominado MessageType, e consiste em uma enumeração que possui uma entrada específica para cada mensagem. Cada mensagem se relaciona com uma QoS Policy, que é definida através de um conjunto de QoS Parameters. A entidade chamada Resource Description contém uma descrição de todos os recursos da nuvem sob uma representação em forma de ontologia, descrito através do formato Web Ontology Language (OWL) (AMIN et al., 2012). A ontologia armazenada por esta entidade reflete a estrutura de implantação da nuvem, com cada nível hierarquia representando um objeto diferente como fornecedor, middleware,aplicação, capacidade, sistema operacional e outros. Esta ontologia é usada em conjunto com QoS Policies, que identificam o melhor caminho para a entrega de um Message para um Subscriber específico. O modelo de comunicação oferecido pelo ICME é próprio para interação entre aplicações cujas partes são executada em domínios distintos. O eCaMid, em contrapartida foi pensado para ser executado em uma única nuvem, como um cluster único. O ICME poderia ser utilizado como intermediário de múltiplos clusters do eCaMid, cada um implantado em um conjunto de recursos diferentes, como, por exemplo, diferentes provedores de nuvem presentes em uma única federação. O segundo tipo de interoperabilidade é implementado pelo middleware conhecido como IBM Altocumulus (MAXIMILIEN et al., 2009). O IBM Altocumulus visa tornar possível a implantação de uma aplicação sobre múltiplos provedores de IaaS públicos (i.e. AWS), provedores de PaaS (i.e. GAE) e nuvens privadas (como Eucalyptus). Além dos provedores de nuvem, o middleware também visa a implantação de aplicações em diferentes linguagens de 5.2. TRABALHOS DE MIDDLEWARE DESENVOLVIDO PARA NUVEM 88 programação e frameworks, como Ruby on Rails 1 , Python/Django 2 , JavaEE3 e Hadoop 4 . Por suportar esses diferentes frameworks, o Autocumulus visa execução de diferentes tarefas em múltiplas nuvens, como é o caso de criar instâncias, executar imagens e configurar componentes. Também é objetivo do middleware permitir a repetição da execução das mesmas tarefas, regras e topologias em múltiplas nuvens, assim como a capacidade de monitorar métricas que medem o desempenho das aplicações. A arquitetura do Altocumulus é composto de um dashboard, que define uma interface para usuários do middleware, destinadada a definir as melhores práticas de implantação de aplicações e gerenciar as credenciais de acesso à diferentes provedores de nuvem. A API e o API Tester são componentes que expõem a API Representational state transfer (REST) do Altocumulus. O Core é um componente que implementa a API, que é usada pelo Dashboard e as aplicações dos usuários. O Core contém um conjunto de scripts, regras e adaptadores de nuvem que permitem a execução de ações em múltiplas nuvens para diferentes tipos de usuários (MAXIMILIEN et al., 2009). O eCaMid, assim como o Altocumulus, foi pensado como uma plataforma que pudesse ser implantada em diversos provedores de nuvem. O eCaMid no entanto, tem um escopo mais restrito, por ser pensado como um middleware que deve ser implantado em nuvens do tipo IaaS para apoiar o desenvolvimento de aplicações orientadas a objeto que sejam compatíveis com a tecnologia Java. No entanto, como o eCaMid é um middleware orientado a objetos, sua principal função é fornecer um modelo de programação para aplicações de nuvem, enquanto o Altocumulus provisiona e configura diferentes aplicações em diferentes tipos de nuvens diferentes. O Altocumulus e o eCaMid poderiam funcionar de forma complementar, onde o primeiro seria usado para provisionar e configurar o segundo em diferentes provedores e máquinas virtuais. 5.2.4 Elasticidade A elasticidade é uma característica bastante peculiar ao modelo de computação em nuvem. A elasticidade é a capacidade de diminuir ou aumentar os recursos de nuvem de acordo com a demanda da aplicação, evitando os riscos associados ao subdimensionamento e superdimensionamento da infraestrutura. Para que um middleware ofereça suporte a elasticidade, ele deve apresentar meios para que a aplicação continue funcionando em decorrência da reconfiguração dinâmica da infraestrutura ou que o middleware forneça serviços específicos que gerencie de forma ativa a elasticidade, com a implantação e desligamento de outros nós. Os trabalhos que serão mostrados a seguir procuram atender pelo menos uma dessas características. RANJAN et al. (2010), em seu trabalho, desenvolveu um middleware baseado em uma arquitetura P2P cuja finalidade é auxiliar na descoberta de serviços, provisionar aplicações em 1 http://rubyonrails.org/ 2 https://www.djangoproject.com/ 3 http://www.oracle.com/technetwork/java/javaee/overview/index.html 4 http://hadoop.apache.org/ 5.2. TRABALHOS DE MIDDLEWARE DESENVOLVIDO PARA NUVEM 89 nós específicos da infraestrutura de nuvem e proporcionar um mecanismo de balanceamento de carga. A vantagem do uso de plataformas P2P no contexto de elasticidade é a sua capacidade de se manter funcional mesmo em decorrência de desligamento e ativação de novas máquinas virtuais, e de conter mecanismos de comunicação de alta escalabilidade. O middleware conhecido como Cloud Peers é parte de uma oferta de PaaS e é composto de três camadas. A primeira camdada consiste em uma infraestrutura de roteamento autoorganizável baseada em DHT, fornecendo um overlay para diversas máquinas virtuais, mantendo uma tabela de roteamento para cada endereço IP de um peer. A segunda camada oferece mecanismos de organização de dados, índices distribuído e replicação. Estes índices suportam o armazenamendo de chaves e queries multidimensionais, onde cada registro é armazenado em múltiplos nós, evitando a perda de informação em caso de falha de um peer. A terceira consiste em serviços de descoberta de nós, coordenação e troca de mensagens. Através dos serviços da terceira camada, são registrados as máquinas virtuais existentes, os serviços publicados em cada um e mecanismos de troca de mensagens baseado no padrão Publish/Subscribe (RANJAN et al., 2010). O eCaMid também utiliza um mecanismo de comunicação P2P para localizar e coordenar diversos nós baseada em JGroups, mas que funciona de forma diferente de uma DHT. eCaMid e o Cloud Peers também diferem por suas finalidades. O principal foco do eCaMid é proporcionar um modelo de programação baseado em objetos distribuídos. Já a finalidade do Cloud Peers é prover mecanismos eficiente de provisionamento de aplicações em máquinas virtuais e oferecer serviços de localização e coordenação. Um outro trabalho tem a finalidade de prover serviços de elasticidade (JAYARAM, 2013). O middleware chamado de ElasticRMI fornece uma extensão ao middleware Remote Method Invocation (RMI), um middleware orientado a objetos que é parte do núcleo da linguagem java. O ElasticRMI define um conceito de um Elastic Object Pool, um conjunto de objetos (baseados no padrão Object Group), que está distribuído em diferentes nós de uma infraestrutura. Invocações direcionadas a um dos objetos presentes no Elastic Object Pool são direcionadas aos demais membros, como um mecanismo de balanceamento de carga. Um sistema de armazenamento chamado Hyperdex (HYPERDEX, 2014) é usado para armazenar o estado dos objetos distribuídos. Um framework de gerenciamento de cluster, chamado Apache Mesos (APACHE MESOS, 2014), é responsável por distribuir processos de um Elastic Object Pool entre várias máquinas físicas ou virtuais (JAYARAM, 2013). O eCaMid e o ElasticRMI são bastante semelhantes, pois ambos são middlewares orientados a objetos que visam manter serviços de suporte à elasticidade. Ambos utilizam o padrão de projeto Object Group para distribuir requisições remotas entre diversos nós. Algumas características, no entanto, diferenciam o eCaMid e o ElasticRMI. Enquanto o balanceamento de carga realizado pelo ElasticRMI é realizado para um grupo formado por um conjunto de objetos semelhantes, o mesmo mecanismo, no eCaMid, é realizado para um grupo de nós semelhantes de uma mesma infraestrutura. Um nó do eCaMid pode conter vários 5.2. TRABALHOS DE MIDDLEWARE DESENVOLVIDO PARA NUVEM 90 objetos distribuídos, que possuem alguma dependência entre si. O eCaMid também suporta estilos de comunicação Publish/Subscribe e a coordenação de tarefas periódicas em um cluster. O sistema de armazenamento e coordenação utilizado pelo eCaMid utiliza um modelo P2P que é embarcado no próprio middleware visando facilitar o deployment e configuração, enquanto o ElasticRMI depende de serviços instalados externamente como o Hyperdex e Apache Mesos. Estes serviços também precisam ser provisionados e dimensionados visando os requisitos não funcionais de escalabilidade, desempenho e disponibilidade para que o ElasticRMI possa adquirir estas mesmas características. O ElasticRMI, no entanto, é capaz de realizar o redimensionamento do tamanho de um Elastic Object Pool dinamicamente, baseado em métricas de desempenho. Embora provedores de nuvem, tipicamente, não possuam instalações nativas de um framework como Apache Mesos, este poderia ser útil como parte de uma oferta de PaaS. O eCaMid ainda carece de um mecanismo semelhante, e poderia se beneficiar de ferramentas de provisionamento e implantação. 5.2.5 Outros requisitos não funcionais de nuvem Diferentes requisitos não funcionais de computação em nuvem podem motivar o desenvolvimento de arquiteturas e a criação de serviços de middleware. Entre os requisitos mencionados nesta seção, temos segurança, confiabilidade e tolerância à falhas. O trabalho desenvolvido por CAMPBELL; MONTANARI; FARIVAR (2012) define uma arquitetura de middleware para aplicações de missão crítica executadas em um ambiente de computação em nuvem. Estes ambientes precisam suportar requisitos restritos de segurança, disponibilidade e desempenho em tempo real. Aplicações de missão crítica precisam ser sobretudo confiáveis, com a garantia que determinada operação foi realmente concluída em um intervalo predeterminado. Para que seja possível garantir estes requisitos, deve ser possível utilizar mecanismos de monitoramento robustos, que possam identificar de forma imediata e confiável problemas de segurança e disponibilidade. Ao mesmo tempo este middleware de missão crítica precisa de agentes que respondam de imediato à violações detectadas. O middleware for assured clouds contém um subsistema composto por agentes que recebem eventos de diversas fontes, sejam estas externas como é o caso de switches openflow, dispositivos que utilizam o protocolo Simple Network Management Protocol (SNMP) (roteadores e switches) e Intrusion Detection Systems (IDSs), ou de fontes internas, que utilizam agregadores de evento que fazem parte da infraestrutura do middleware. Estes eventos coletados por um agente são encaminhados a um motor de inferência de regras interno ao próprio agente, que verificam problemas de conformidade. Caso seja detectado uma violação de conformidade, estes devem notificar os componentes que administram os sistemas de comunicação, gerando mudanças na configuração e comportamento, impedindo que novos erros sejam repetidos (CAMPBELL; MONTANARI; FARIVAR, 2012). O eCaMid não foi pensado no contexto de aplicações de missão críticas, e não é meta 5.2. TRABALHOS DE MIDDLEWARE DESENVOLVIDO PARA NUVEM 91 de seu desenvolvimento e evolução garantir estes requisitos. No entanto, os agentes de monitoramento descritos por CAMPBELL; MONTANARI; FARIVAR (2012) poderiam ser providos como módulos externos ao eCaMid, para satisfazer os requisitos não funcionais de aplicações específicas. BEHL et al. (2012), em seu trabalho, definiu uma solução para execução de diferentes workflows baseados em web services, com suporte a tolerância a falhas. No núcleo da solução desenvolvida, há um motor de processos de negócio compatível com a linguagem Business Process Execution Language (WS-BPEL). Um processo de negócio é um fluxo de ações de negócio complexas que invocam capacidades específicas de diversos web services, estes que realizam operações de negócio de maior granularidade. Motores WS-BPEL precisam guardar dados intermediários, tratar exceções e expressar fluxos de execução. No entanto, infrastruturas tradicionais que utilizam esta tecnologia são deficientes em mecanismos de tolerância a falhas. Para solucionar o problema, os motores WS-BPEL e web services precisam ser replicados. Os web services, em particular, devem ser acessados através de proxies, que usam um serviço de coordenação externo, o Zookeeper (APACHE ZOOKEEPER, 2014). Este serviço de coordenação serve para armazenar configuração e informação relevante para o sistema, detectar quando algum dos nós falha e realizar a ordenação das requisições (BEHL et al., 2012). Uma definição de processo de negócio, ao ser carregada pelo motor WS-BPEL, deve ser transformada para incluir estes proxies no lugar de chamadas diretas aos webservices. As requisições entregues pelos motores de regra de negócio aos web services devem conter uma semântica de At Most Once, para assegurar que uma operação de negócio tenha sido realizada múltiplas vezes em um fluxo BEHL et al. (2012). Assim como o eCaMid, o trabalho desenvolvido por BEHL et al. (2012) faz uso de um mecanismos de coordenação de processos, neste caso o Zookeeper. O Zookeeper, no entanto, atua de forma externa à aplicação, implantado como um conjunto de processos independentes. 5.2.6 Discussão Foi possível observar nas subseções anteriores vários trabalhos que utilizam middleware para implementar várias funcionalidades como multitenancy, interoperabilidade, elasticidade e dar apoio a outros requisitos não funcionais de aplicações distribuídas. Muitos dos middlewares desenvolvidos por estes trabalhos, no entanto, nem são middlewares orientados a objeto, nem possuem foco em modelos de programação distribuídos. Apenas parte desses trabalhos possuem implementação e foram testados em uma nuvem real, como o eCaMid. Alguns dos trabalhos de middleware desenvolvidos nestas pesquisas possuem mecanismos bastante similares aos implementados no eCaMid, mas que se diferenciam por abordar estratégias diferentes ou modelos de programação distintos. Através deste estudo, também foi possível verificar vários pontos de melhoria e avanços a serem implmentados em trabalhos futuros. 5.2. TRABALHOS DE MIDDLEWARE DESENVOLVIDO PARA NUVEM 5.2.7 92 Considerações finais Neste capítulo, foram listadas as tecnologias usadas pelo eCaMid para implementar seus mecanismos de coordenação e compartilhamento de estado. Em seguida, foram mencionados vários trabalhos que visam a utilização de middleware para implementar várias funcionalidades como multitenacidade, interoperabilidade, elasticidade e dar apoio a outros requisitos não funcionais. Uma breve discussão foi iniciada para elicitar a motivação do desenvolvimento do eCaMid. 93 6 Considerações Finais Os primeiros capítulos explicaram as principais motivações para o desenvolvimento do eCaMid e as ideias básicas que fundamentam os conceitos utilizados na concepção da sua arquitetura. Foram explicados os principais conceitos de computação em nuvem e elasticidade. Também foi realizado um estudo sobre os padrões arquiteturais e de projeto, e seus relacionamentos, para definir os blocos básicos e uma linguagem padrão para os componentes do projeto do eCaMid. O terceiro capítulo introduziu os aperfeiçoamentos realizados à arquitetura original, para aprimorar o suporte à elasticidade. Como contribuições principais do eCaMid, podemos mencionar o uso de mecanismos de coordenação, replicação e balanceamento de carga, que visam aumentar a escalabilidade do middleware quando novos nós são adicionados, e continuar funcionando quando esses nós são desligados. Adicionalmente, o eCaMid introduziu novas funcionalidades (tarefas periódicas, e comunicação Publish/Subscribe) que aumentam o escopo do eCaMid para tipos de carga de trabalho que são complementares ao estilo de comunicação de middlewares orientados a objetos e são relevantes para o paradigma de computação em nuvem. Uma avaliação experimental foi usada, no quarto capítulo, para avaliar o comportamento do eCaMid em diferentes cenários. Dada as condições do experimento, os mecanismos de balanceamento de carga do eCaMid mostraram um melhor resultado quando foram utilizados objetos remotos que não possuem estado. Quando esses objetos remoto possuem estado, a sincronização deste entre vários nós apresentou uma perda considerável de desempenho, mas em contrapartida, tornou possível que o mesmo objeto fosse acessado consistentemente entre vários nós. No quinto capítulo, foi realizado um breve estudo sobre os trabalhos de middleware que foram desenvolvidos para a nuvem. Foram identificados diversos pontos comuns e divergentes entre o eCaMid e esses trabalhos, assim como estratégias usadas nestes que podem servir como melhorias para o eCaMid em trabalhos futuros. Através deste trabalho foi possível criar um middleware orientado a objetos que é capaz de utilizar a elasticidade de um ambiente de nuvem para aprimorar seus mecanismos de distribuição. Este middleware se baseou mas melhores práticas para o desenvolvimento de aplicações na 6.1. TRABALHOS FUTUROS 94 nuvem, levando em conta as peculiaridades deste ambiente e desenvolveu mecanismos de suporte à elasticidade dentro do próprio middleware. Ainda que o eCaMid careça da mesma maturidade de outras soluções de middleware do mercado e da academia, este pode servir como prova de conceito para implementação de mecanismos de suporte à elasticidade em outras plataformas mais maduras. Os mecanismos usados neste trabalho podem também ser adaptados para outros tipos de modelo de comunicação, como é o caso de servidores web, balanceadores de carga inteligentes e servidores de aplicação. 6.1 Trabalhos Futuros A evolução do eCaMid pode ser realizada em diversas direções. O sistema atual de sincronização de estado do eCaMid é limitado pelas capacidades do Infinispan, que provê as abstrações necessárias para a implementação de um serviço de armazenamento em memória distribuído. O eCaMid pode ser expandido para utilizar outros key-value stores distribuídos, como é o caso do Redis1 e Memcached2 . O desempenho destas soluções de armazenamento pode ser comparado e avaliado em que cenários cada uma dessas tecnologias apresenta o melhor resultado. O suporte à elasticidade pode ser aprimorado através da implementação de um serviço que realize a implantação e provisionamento de máquinas virtuais de forma automática, com base em parâmetros de qualidade coletados a partir dos componentes de gerenciamento do eCaMid. O uso de multitenancy possibilitará um controle mais granular sobre a elasticidade, provendo isolamento a múltiplas aplicações em um mesmo cluster do eCaMid. O uso de interoperabilidade entre múltiplas nuvens pode favorecer à implantação do eCaMid em um cenário multi-cluster. Este cenário consiste em um conjunto de clusters que utilizam algum mecanismo de integração (como mensagens assíncronas) e balancemento de carga de acordo garantias de nível de serviço de múltiplos provedores ou distribuição geográfica. A implementação atual do eCaMid não oferece suporte a mecanismos de segurança. Esta implementação poderia ser estendida para incluir serviços de autenticação e controle de acesso baseado em políticas e papéis. 1 http://redis.io/ 2 http://memcached.org/ 95 Referências ABBADI, I. Middleware Services at Cloud Virtual Layer. In: COMPUTER AND INFORMATION TECHNOLOGY (CIT), 2011 IEEE 11TH INTERNATIONAL CONFERENCE ON. Anais. . . [S.l.: s.n.], 2011. p.115–120. ABBADI, I. M. Middleware Services at Cloud Application Layer. In: ABRAHAM, A. et al. (Ed.). Advances in Computing and Communications. [S.l.]: Springer Berlin Heidelberg, 2011. p.557–571. (Communications in Computer and Information Science, v.193). 10.1007/978-3-642-22726-4_58. AMIN, M. B. et al. Intercloud Message Exchange Middleware. In: INTERNATIONAL CONFERENCE ON UBIQUITOUS INFORMATION MANAGEMENT AND COMMUNICATION, 6., New York, NY, USA. Proceedings. . . ACM, 2012. p.79:1–79:7. (ICUIMC ’12). APACHE JMeter. Accessed: 2014-04-30, http://jmeter.apache.org/. APACHE Mesos. Accessed: 2014-07-20, http://mesos.apache.org/. APACHE Zookeeper. Accessed: 2014-07-15, http://zookeeper.apache.org/. AZEEZ, A. et al. Multi-tenant SOA middleware for cloud computing. In: CLOUD COMPUTING (CLOUD), 2010 IEEE 3RD INTERNATIONAL CONFERENCE ON. Anais. . . [S.l.: s.n.], 2010. p.458–465. BABAR, M. A.; CHAUHAN, M. A. A Tale of Migration to Cloud Computing for Sharing Experiences and Observations. In: ND INTERNATIONAL WORKSHOP ON SOFTWARE ENGINEERING FOR CLOUD COMPUTING, 2., New York, NY, USA. Proceedings. . . ACM, 2011. p.50–56. (SECLOUD ’11). BAKOUCH, H. S. Probability, Markov chains, queues, and simulation. Journal of Applied Statistics, [S.l.], v.38, n.8, p.1746–1746, 2011. BALIGA, J. et al. Green Cloud Computing: balancing energy in processing, storage, and transport. Proceedings of the IEEE, [S.l.], v.99, n.1, p.149–167, Jan 2011. BAN, B.; BLAGOJEVIC, V. Reliable group communication with JGroups 3.x. Accessed: 2014-06-30, http://www.jgroups.org/manual/html/index.html. BEHL, J. et al. Providing Fault-tolerant Execution of Web-service-based Workflows Within Clouds. In: ND INTERNATIONAL WORKSHOP ON CLOUD COMPUTING PLATFORMS, 2., New York, NY, USA. Proceedings. . . ACM, 2012. p.7:1–7:6. (CloudCP ’12). BUSCHMANN, F.; HENNEY, K.; SCHMIDT, D. C. Pattern-Oriented Software Architecture Volume 4: a pattern language for distributed computing (v. 4). [S.l.]: Wiley, 2007. CALHEIROS, R. N. et al. The Aneka platform and QoS-driven resource provisioning for elastic applications on hybrid Clouds. Future Generation Computer Systems, [S.l.], v.28, n.6, p.861 – 870, 2012. Including Special sections SS: Volunteer Computing and Desktop Grids and SS: Mobile Ubiquitous Computing. REFERÊNCIAS 96 CAMPBELL, R.; MONTANARI, M.; FARIVAR, R. A middleware for assured clouds. Journal of Internet Services and Applications, [S.l.], v.3, n.1, p.87–94, 2012. CHAUDHARY, N. et al. JBoss Enterprise Application Platform 6.2 Administration and Configuration Guide. Accessed: 2014-06-30, https://access.redhat.com/ documentation/en-US/JBoss_Enterprise_Application_Platform/6.2/ html/Administration_and_Configuration_Guide/index.html. DRAGO, I. et al. Inside Dropbox: understanding personal cloud storage services. In: ACM CONFERENCE ON INTERNET MEASUREMENT CONFERENCE, 2012., New York, NY, USA. Proceedings. . . ACM, 2012. p.481–494. (IMC ’12). EMMERICH, W.; KAVEH, N. Component technologies: java beans, com, corba, rmi, ejb and the corba component model. In: SOFTWARE ENGINEERING, 2002. ICSE 2002. PROCEEDINGS OF THE 24RD INTERNATIONAL CONFERENCE ON. Anais. . . [S.l.: s.n.], 2002. p.691–692. FOX, A. et al. Above the clouds: a berkeley view of cloud computing. Dept. Electrical Eng. and Comput. Sciences, University of California, Berkeley, Rep. UCB/EECS, [S.l.], v.28, p.13, 2009. FURHT, B. Cloud Computing Fundamentals. In: FURHT, B.; ESCALANTE, A. (Ed.). Handbook of Cloud Computing. [S.l.]: Springer US, 2010. p.3–19. GAMMA, E. et al. Design Patterns: abstraction and reuse of object-oriented design. In: NIERSTRASZ, O. (Ed.). ECOOP’ 93 — Object-Oriented Programming. [S.l.]: Springer Berlin Heidelberg, 1993. p.406–431. (Lecture Notes in Computer Science, v.707). GHOSH, S. Distributed systems: an algorithmic approach. [S.l.]: CRC press, 2010. GORTON, I. Essential software architecture. [S.l.]: Springer, 2011. GUPTA, I. et al. Kelips: building an efficient and stable p2p dht through increased memory and background overhead. In: KAASHOEK, M.; STOICA, I. (Ed.). Peer-to-Peer Systems II. [S.l.]: Springer Berlin Heidelberg, 2003. p.160–169. (Lecture Notes in Computer Science, v.2735). HERRICK, D. R. Google This!: using google apps for collaboration and productivity. In: ANNUAL ACM SIGUCCS FALL CONFERENCE: COMMUNICATION AND COLLABORATION, 37., New York, NY, USA. Proceedings. . . ACM, 2009. p.55–64. (SIGUCCS ’09). HOHPE, G.; WOOLF, B. Enterprise integration patterns: designing, building, and deploying messaging solutions. [S.l.]: Addison-Wesley Professional, 2004. HOMER, A. et al. Cloud Design Patterns: prescriptive architecture guidance for cloud applications. [S.l.]: Microsoft patterns & practices, 2014. HYPERDEX. Accessed: 2014-07-20, http://hyperdex.org/. JAIN, R. The art of computer system performance analysis: techniques for experimental design, measurement, simulation and modeling. New York: John Willey, [S.l.], 1991. REFERÊNCIAS 97 JAYARAM, K. Elastic Remote Methods. In: EYERS, D.; SCHWAN, K. (Ed.). Middleware 2013. [S.l.]: Springer Berlin Heidelberg, 2013. p.143–162. (Lecture Notes in Computer Science, v.8275). JIN, H. et al. Tools and Technologies for Building Clouds. In: ANTONOPOULOS, N.; GILLAM, L. (Ed.). Cloud Computing. [S.l.]: Springer London, 2010. p.3–20. (Computer Communications and Networks). KäCHELE, S.; HAUCK, F. J. Component-based Scalability for Cloud Applications. In: INTERNATIONAL WORKSHOP ON CLOUD DATA AND PLATFORMS, 3., New York, NY, USA. Proceedings. . . ACM, 2013. p.19–24. (CloudDP ’13). KEMP, C.; GYGER, B. Professional Heroku Programming. [S.l.]: John Wiley & Sons, 2013. KIRCHER, M.; JAIN, P. Pattern-oriented software architecture vol 3: patterns for resource management. [S.l.]: Wiley, 2004. LEWIS, G. Role of Standards in Cloud-Computing Interoperability. In: SYSTEM SCIENCES (HICSS), 2013 46TH HAWAII INTERNATIONAL CONFERENCE ON. Anais. . . [S.l.: s.n.], 2013. p.1652–1661. MAFFEIS, S. et al. The Object Group Design Pattern. In: COOTS. Anais. . . [S.l.: s.n.], 1996. v.96, p.12–12. MARCHIONI, F. Infinispan Data Grid Platform. [S.l.]: Packt Publishing Ltd, 2012. MARSTON, S. et al. Cloud computing — The business perspective. Decision Support Systems, [S.l.], v.51, n.1, p.176 – 189, 2011. MAXIMILIEN, E. M. et al. IBM Altocumulus: a cross-cloud middleware and platform. In: ACM SIGPLAN CONFERENCE COMPANION ON OBJECT ORIENTED PROGRAMMING SYSTEMS LANGUAGES AND APPLICATIONS, 24., New York, NY, USA. Proceedings. . . ACM, 2009. p.805–806. (OOPSLA ’09). MERLE, P.; ROUVOY, R.; SEINTURIER, L. A reflective platform for highly adaptive multi-cloud systems. In: ADAPTIVE AND REFLECTIVE MIDDLEWARE ON PROCEEDINGS OF THE INTERNATIONAL WORKSHOP, New York, NY, USA. Anais. . . ACM, 2011. p.14–21. (ARM ’11). MONTRESOR, A.; DAVOLI, R.; BABAOGLU, O. Middleware for Dependable Network Services in Partitionable Distributed Systems. SIGOPS Oper. Syst. Rev., New York, NY, USA, v.35, n.1, p.73–96, Jan. 2001. MORAIS, T. de; LIBERALQUINO, D.; ROSA, N. Cloud-Aware Middleware. In: ADVANCED INFORMATION NETWORKING AND APPLICATIONS (AINA), 2013 IEEE 27TH INTERNATIONAL CONFERENCE ON. Anais. . . [S.l.: s.n.], 2013. p.780–787. OPENSTACK Cloud Administrator Guide. Accessed: 2014-06-20, http://docs.openstack.org/admin-guide-cloud/content/. RANJAN, R. et al. Peer-to-Peer Cloud Provisioning: service discovery and load-balancing. In: ANTONOPOULOS, N.; GILLAM, L. (Ed.). Cloud Computing. [S.l.]: Springer London, 2010. p.195–217. (Computer Communications and Networks). REFERÊNCIAS 98 REESE, G. Cloud application architectures: building applications and infrastructure in the cloud. [S.l.]: "O’Reilly Media, Inc.", 2009. RIMAL, B.; CHOI, E.; LUMB, I. A Taxonomy, Survey, and Issues of Cloud Computing Ecosystems. In: ANTONOPOULOS, N.; GILLAM, L. (Ed.). Cloud Computing. [S.l.]: Springer London, 2010. p.21–46. (Computer Communications and Networks). SADJADI, S. M.; MCKINLEY, P. K. A survey of adaptive middleware. Michigan State University Report MSU-CSE-03-35, [S.l.], 2003. SANDERSON, D. Programming Google App Engine: build and run scalable web apps on google’s infrastructure. [S.l.]: "O’Reilly Media, Inc.", 2009. SCHMIDT, D. C. Middleware for Real-time and Embedded Systems. Commun. ACM, New York, NY, USA, v.45, n.6, p.43–48, June 2002. SCHMIDT, D. C. et al. Pattern-Oriented Software Architecture, Patterns for Concurrent and Networked Objects. [S.l.]: John Wiley & Sons, 2013. v.2. SHEN, H.; XU, C.-Z. Hash-based proximity clustering for efficient load balancing in heterogeneous {DHT} networks. Journal of Parallel and Distributed Computing, [S.l.], v.68, n.5, p.686 – 702, 2008. SIEGELE, L. Let it rise: a special report on corporate it. [S.l.]: Economist Newspaper, 2008. SURTANI, M. et al. Infinispan User Guide. Accessed: 2014-06-30, http://infinispan.org/docs/6.0.x/user_guide/user_guide.html. TALUKDER, A.; ZIMMERMAN, L.; A, P. Cloud Economics: principles, costs, and benefits. In: ANTONOPOULOS, N.; GILLAM, L. (Ed.). Cloud Computing. [S.l.]: Springer London, 2010. p.343–360. (Computer Communications and Networks). TURAN, M. S. et al. Recommendation for password-based key derivation. NIST special publication, [S.l.], v.800, p.132, 2010. VANBRABANT, R. Google Guice: agile lightweight dependency injection framework. [S.l.]: Apress, 2008. VARIA, J. Architecting for the cloud: best practices. Amazon Web Services, [S.l.], 2010. VARIA, J.; MATHEW, S. Overview of amazon web services. Amazon Web Services, [S.l.], 2012. VÖLTER, M.; KIRCHER, M.; ZDUN, U. Remoting Patterns: foundations of enterprise, internet and realtime distributed object middleware. [S.l.]: Wiley. com, 2005. WILDER, B. Cloud Architecture Patterns. [S.l.]: "O’Reilly Media, Inc.", 2012.