FootBot: Uma Arquitetura de Microsserviços na Nuvem para Predição de Resultados de Partidas de Futebol. Victor Aguiar Souza Springer - PDF
FootBot: Uma Arquitetura de Microsserviços na Nuvem para Predição de Resultados de Partidas de Futebol. Victor Aguiar Souza Springer
Download "FootBot: Uma Arquitetura de Microsserviços na Nuvem para Predição de Resultados de Partidas de Futebol. Victor Aguiar Souza Springer"
Rita Bernardes Bugalho
1 UNIVERSIDADE FEDERAL DO ESTADO DO RIO DE JANEIRO CENTRO DE CIÊNCIAS EXATAS E TECNOLOGIA ESCOLA DE INFORMÁTICA APLICADA FootBot: Uma Arquitetura de Microsserviços na Nuvem para Predição de Resultados de Partidas de Futebol Victor Aguiar Souza Springer Orientador Leonardo Guerreiro Azevedo RIO DE JANEIRO, RJ BRASIL JULHO DE 2018
2 Catalogação informatizada pelo autor
3 Footbot: Uma Arquitetura de Microsserviços na Nuvem para Predição de Resultados de Partidas de Futebol Victor Aguiar Souza Springer Projeto de Graduação apresentado à Escola de Informática Aplicada da Universidade Federal do Estado do Rio de Janeiro (UNIRIO) para obtenção do título de Bacharel em Sistemas de Informação. Aprovado por: RIO DE JANEIRO, RJ BRASIL. JULHO DE 2018
4 Agradecimentos Gostaria de agradecer, primeiramente, aos meus pais, Sonia e Elcio, e a minha avó, Neuza, por todo o amor, por terem moldado o meu caráter, me dado educação, feito todos os esforços para que nunca me faltasse nada, e por quem eu tenho inestimável admiração. Foi graças a eles que cheguei até aqui. Aos meus irmãos, Vinícius e Cíntia, pelo carinho, apoio incondicional e por serem tão pacientes comigo. Meus maiores exemplos de bons aprendizes. A minha companheira, Julianne, pelo nosso amor, por evoluirmos juntos, por me inspirar e pelos planos compartilhados; por ter acompanhado de perto e me dado suporte emocional durante toda a graduação. Ao meu amigo de longa data, Patrick, pela irmandade e consideração, por me fortalecer independentemente da ocasião. Ao corpo docente da Unirio, pela excelência no ensino e dedicação aos alunos. Em especial aos professores: Leonardo Azevedo, pela orientação e dedicação a este trabalho, e Márcio Barros, por aceitar o convite para estabelecer a banca. Ao professor da UFRRJ, Henrique Prado Sousa, que também se disponibilizou para a formação da banca. Aos meus amigos da Unirio, por terem feito parte da minha trajetória acadêmica e que continuarão fazendo parte da minha vida: Allan Magalhães, Amanda Rodrigues, Daniel Villaça, Lucas Lins, Renard Ferreira e Thiago Albuquerque. A todos os amigos que fiz na UFRJ, pelos bons momentos vividos, em especial aos que ainda fazem parte do meu dia a dia: Eduardo Andrade, Gabriel Souza e Stefan Teixeira. Por fim, aos grandes profissionais com quem trabalho ou já trabalhei, pela colaboração e aprendizado diário: André Goulart, Carlos André Oliveira, Gabriel Sepulveda, Diego Bernardes, Lucas Nascimento, Lucas Vieira, Pedro Rosa e Wédney Yuri. 1
5 RESUMO Vivemos em uma era na qual uma parcela cada vez maior da população mundial está conectada à internet e o tráfego de dados cresce progressivamente. Junto a isto, orquestradas pela demanda dessa nova era, a engenharia de software se reinventa, novas formas de serviços surgem, e as comunidades do mundo open source evoluem e criam novas ferramentas que simplificam o desenvolvimento de aplicações. Este trabalho apresenta o desenvolvimento de uma aplicação que faz predição de resultados de partidas de futebol. O objetivo foi descrever o desenvolvimento de um sistema de alta disponibilidade e performance, utilizando arquitetura de microsserviços e computação em nuvem. Para isto, também foram utilizadas tecnologias de ponta como a linguagem de programação Golang, banco de dados não relacional, infraestrutura como código, entre outras. Palavras-chave: Microsserviços, Computação em Nuvem, Futebol, Predição, Golang. 2
6 ABSTRACT We live in an era where an increasing part of the world s population is connected to the internet and the data traffic progressively grows. Next to it, leaded by the demand of this new era, software engineering is reinvented, new service forms emerge, and the open source communities evolve and create new tools that make application development simpler. This work presents the development of an application that predicts football matches results. The aim was to describe the development of a high availability and performance system, using microservices architecture and cloud computing. For this, cutting-edge technologies were used as well, such as Golang programming language, non-relational database, infrastructure as code, among others. Keywords: Microservices, Cloud Computing, Football, Prediction, Golang. 3
7 Índice 1 Introdução Fundamentação Teórica Arquitetura de Microsserviços Monolíticos e Microsserviços Características Benefícios Computação em Nuvem Software como Serviço (SaaS) Plataforma como Serviço (PaaS) Infraestrutura como Serviço (IaaS) Tecnologias Utilizadas Golang React MongoDB Docker Terraform GitLab Wrk Desenvolvimento do FootBot Visão Geral Fluxo de Dados Algoritmo Microsserviços Componentes Endpoints Infraestrutura em Nuvem
8 4.4.1 Cloudflare CDN AWS EC AWS ECS AWS Elastic Load Balancing AWS Lambda AWS CloudWatch MongoDB Atlas Resultados Predições Teste de Carga CDN Conclusão Considerações Finais Trabalhos Futuros Referências Bibliográficas Apêndice A Codificação do Projeto
9 Índice de Tabelas Tabela 1. Endpoints da API Match Tabela 2. Endpoints da API Player Tabela 3. Endpoints da API Team Tabela 4. Endpoints da API Prediction Tabela 5. Endpoint dos Workers
10 Índice de Figuras Figura 1. Monolíticos e Microsserviços Figura 2. Gerenciamento de Dados: Monolíticos e Microsserviços Figura 3. Microsserviços permitem adotar diferentes tecnologias facilmente Figura 4. Escalando cada microsserviço de acordo com sua necessidade Figura 5. Computação em Nuvem e seus modelos de serviços Figura 6. Exemplo da execução de uma query ao MongoDB Figura 7. Exemplo de código HCL Figura 8. Exemplo de configuração de um delivery pipeline Figura 9. Tela inicial do FootBot Figura 10. Tela do FootBot de possíveis resultados para uma partida Figura 11. Estrutura de dados JSON de um time Figura 12. Resposta do cálculo de possíveis resultados da API de predição Figura 13. Diagrama de Componentes do FootBot Figura 14. Infraestrutura do FootBot Figura 15. Visão geral do dashboard do EC Figura 16. Visão geral do dashboard do ECS Figura 17. Visualização dos serviços do FootBot no ECS Figura 18. Visualização das instâncias EC2 do cluster no ECS Figura 19. Visualização das regras de evento do CloudWatch Figura 20. Probabilidades calculadas pelo FootBot Parte Figura 21. Probabilidades calculadas pelo FootBot Parte Figura 22. Probabilidades calculadas pelo FootBot Parte Figura 23. Resultados da 10ª rodada da Série A do Campeonato Brasileiro de Figura 24. Resultado do teste de carga com camada de cache da CDN Figura 25. Resultado do teste de carga diretamente na API Figura 26. Taxa de utilização dos processadores durante os testes Figura 27. Gráfico de requisições à Cloudflare Figura 28. Gráficos de performance da Cloudflare Figura 29. Indicadores de segurança da Cloudflare Figura 30. Estrutura de diretório padrão Figura 31. Arquivo match.go Figura 32. Match: arquivo /services/api.go Parte
11 Figura 33. Match: arquivo /services/api.go Parte Figura 34. Match: Trecho do arquivo /domain/match/handler.go Figura 35. Match: Trecho do arquivo /external/mongodb/match.go Figura 36. Função Lambda para ativar o trabalho do Worker Figura 37. Exemplo de objeto JSON enviado pelo AWS CloudWatch
12 Lista de Siglas e Abreviaturas SOA Service-Oriented Architecture RPC Remote Procedure Call DCE Distributed Computing Environment CORBA Common Object Request Broker Architecture EJB Enterprise JavaBeans SOAP Simple Object Access Protocol HTTP Hypertext Transfer Protocol REST Representational State Transfer WS Web Service URI Uniform Resource Identifier TI Tecnologia da Informação JEE Java Enterprise Edition API Application Programming Interface ESB Enterprise Service Bus BPEL Business Process Execution Language AMQP Advanced Message Queuing Protocol SGBD Sistema de Gerenciamento de Banco de Dados SaaS Software as a Service PaaS Platform as a Service IaaS Infrastructure as a Service AWS Amazon Web Services MIT Massachusetts Institute of Technology 9
13 CDN Content Delivery Network BSD Berkeley Software Distribution AGPL Affero General Public License JSON JavaScript Object Notation YAML Acrônimo recursivo que significa YAML Ain t Markup Language DDoS Distributed Denial of Service vcpu Virtual Central Processing Unit OSI Open System Interconnection CORS Cross-Origin Resource Sharing 10
14 1 Introdução Com a evolução da rede de internet, da web e da facilidade de acesso a um público cada vez maior, graças à popularização dos computadores pessoais e smartphones no ano de 2000 havia 400 milhões de pessoas conectadas à internet, em 2015 este número já era superior a 3 bilhões [1], ultrapassamos a era do smart e estamos entrando na era do intelligent, ou seja, das aplicações que possuem algum tipo de inteligência artificial. Deste modo, surge a necessidade das tecnologias de software e de infraestrutura de lidar com grandes volumes de dados. Além disso, uma infinidade de usuários está a todo momento navegando pela rede, tornando imprescindível que uma aplicação web pública esteja preparada para receber uma quantidade massiva de acessos simultâneos. Esta aplicação deve ser capaz de lidar com as transações sem afetar negativamente a experiência do usuário, de forma a manter uma boa estabilidade (baixo tempo de resposta e baixa taxa de erros) e alta disponibilidade. Como exemplo, considere o lucro perdido por uma empresa de e- commerce de uma grande marca que fica indisponível por dez minutos em pleno evento de Black Friday porque não suportou a quantidade de acessos. Junto a isto, com o advento das metodologias ágeis e da quantidade de ferramentas disponíveis somadas à crescente demanda por cada vez mais serviços automatizados online e entregas rápidas pelos times de desenvolvedores, novos desafios surgiram no escopo do desenvolvimento de software. Dentre essas ferramentas, há um crescente número de tecnologias de infraestrutura (hardware, rede, armazenamento etc.), plataforma e aplicação, disponíveis para contrato em forma de serviço sob demanda. Isto elimina, por exemplo, a necessidade de aquisição e manutenção de servidores, roteadores e outros dispositivos físicos. Essa abstração é conhecida por cloud, ou nuvem [2]. 11
15 No campo da engenharia de software, uma arquitetura vem ganhando notável popularidade devido sua simplicidade de implementação, escalabilidade, e agilidade no desenvolvimento de grandes sistemas. Esta é a arquitetura de microsserviços. Neste contexto, o que motivou a realização deste trabalho foi mostrar, de forma exemplificada, o uso da arquitetura de microsserviços e da infraestrutura em nuvem. Para isto, são apresentados paradigmas, definições e ferramentas necessárias para o desenvolvimento de aplicações resilientes (no sentido de escalar os serviços dinamicamente de acordo com a demanda do tráfego) e escaláveis (ou seja, capazes de receber novas funcionalidades de maneira simples, paralela e desacoplada). Este trabalho é, portanto, destinado àqueles que buscam solucionar tanto problemas arquiteturais (que atribuem complexidade ao desenvolvimento do projeto), quanto de desempenho e disponibilidade do produto. Esse exemplo de uso é apresentado com base na concepção de um sistema real: o FootBot, uma aplicação web que calcula probabilidades de resultados de partidas de futebol. O presente trabalho está estruturado em capítulos e, além desta introdução, está dividido da seguinte forma: Capítulo II: Apresenta os principais conceitos: arquitetura de microsserviços e infraestrutura em nuvem. Capítulo III: Descreve as tecnologias adotadas no desenvolvimento do FootBot. Capítulo IV: Apresenta o FootBot, descreve a aplicação das tecnologias e paradigmas empregados em seu desenvolvimento, além de demonstrar o uso de microsserviços e infraestrutura em nuvem nesse software. Capítulo V: Apresenta os resultados obtidos a partir de testes de carga ao FootBot e do seu funcionamento. Capítulo VI: Apresenta as considerações finais e trabalhos futuros. 12
16 2 Fundamentação Teórica 2.1 Arquitetura de Microsserviços O termo Arquitetura de Microsserviços surgiu no decorrer dos últimos anos para descrever uma maneira específica de projetar aplicações de software como conjuntos de serviços de implementação independente [3]. Embora não exista uma definição formal para microsserviços, este conceito pode ser descrito como serviços autônomos, pequenos, que trabalham juntos [4]. A arquitetura de microsserviços é frequentemente interpretada de forma equivocada como uma nova nomenclatura para Arquitetura Orientada a Serviços (SOA). Para entender a diferença, bem como o surgimento e ampla difusão dessa arquitetura, Kyle Brown expõe três observações de Martin Fowler, que segundo este, fundamentaram a concepção dessa nova arquitetura. Estas três observações foram explicadas a partir de uma análise histórica da distribuição de sistemas [5]: I. Simplesmente porque algo pode ser distribuído, não significa que deve ser distribuído: no início dos anos 80, houve a introdução da primeira tecnologia de distribuição de sistemas, a Chamada de Procedimento Remoto (RPC), que originou outras tecnologias como o Distributed Computing Environment (DCE ) e o CORBA (1991). Em cada uma destas tecnologias, a ideia básica era fazer chamadas remotas transparentes para os desenvolvedores, de forma que não importasse se as chamadas ou métodos de procedimentos eram locais ou remotos. Possibilitaria assim, o desenvolvimento de sistemas maiores entre máquinas, evitando problemas de escalabilidade, processamento e de memória que afetavam os sistemas da época (por exemplo, os processadores mais comuns eram de 16 bits, com um espaço de endereço de 64 kb). À medida que os processadores evoluíram e os espaços de endereço locais se tornaram maiores, esse problema perdeu importância. Além disso, com o lançamento do 13
17 primeiro conjunto de implementações grandes do DCE e do CORBA juntamente com a expansão dos espaços de memória, tornou-se evidente que fazer escolhas ruins sobre distribuição de métodos entre máquinas pode ter efeitos indesejáveis no desempenho do sistema. A cultura de distribuir tudo que fosse possível resultou em muitos sistemas com interfaces muito informais. Em sistemas como estes, o gasto adicional de rede superava em muito as vantagens de distribuição. II. Tentar fazer uma chamada distribuída agir como uma chamada local é uma escolha ruim: o padrão de projeto Façade estava relacionado a encapsular as interfaces não estruturadas de um sistema grande em uma única interface mais estruturada para reduzir a informalidade. Foi então desenvolvida a Session Façade. Esta aplicava esse padrão a sistemas distribuídos, identificando as interfaces-chave de alta granularidade de cada subsistema e expondo apenas essas interfaces para distribuição. As primeiras Session Façades foram implementadas com EJB, que, embora fosse um bom componente quando se programava apenas em Java, era complicado, difícil de depurar e não interoperava com outras linguagens ou com produtos de outros fornecedores. Esta falta de interoperabilidade levou diretamente à próxima abordagem, do início ao meio dos anos 2000, que viria a ser conhecida como Arquitetura Orientada a Serviços (SOA). O SOA teve início com uma tecnologia chamada Protocolo Simples de Acesso a Objetos (SOAP). O SOAP é uma maneira de chamar métodos de objetos por HTTP. Ele aproveitou dois artefatos diferentes do mundo da computação no início dos anos 2000: o crescente suporte para HTTP em redes corporativas e o fato de que esse suporte incluía mecanismos para criação de log e depuração de chamadas de rede baseadas em texto. Essa primeira abordagem em torno do SOAP foi útil, pois estabeleceu rapidamente que seria possível interoperar com facilidade entre sistemas implementados em diversas linguagens e em plataformas diferentes. Seu uso, porém, deixou de ser vantajoso para qualquer caso de uso ao ir além desse início simples, incluindo camadas de conceitos adicionais além da simples chamada de método: manipulação de exceção, suporte a transações, segurança e assinaturas digitais foram todos incluídos, atribuindo mais complexidade ao protocolo. III. Sempre que possível, os programas e seus ambientes de tempo de execução devem ser totalmente autocontidos: a indústria, em geral, começou lentamente a 14
18 rejeitar o conceito de camadas processuais inerentes ao SOAP e aos padrões WS-*. Em vez disso, o que se tornou mais difundido foi a adoção do REST. Em vez de atribuir semântica em camada de chamada processual por HTTP, REST trata os verbos HTTP da maneira como foram semanticamente especificados, em termos de criar, ler, excluir e atualizar. Também delineia uma maneira para especificar nomes únicos de entidades por meio de outro princípio da web: o URI. Ao mesmo tempo, a indústria também estava começando a rejeitar outro legado do mundo do Java Platform, Java Enterprise Edition e SOA: o Server Farm (grupo de servidores mantidos por uma empresa). Desde que o Java Enterprise foi introduzido em 1999, havia uma tensão contínua entre os proprietários das aplicações e administradores das aplicações. Nesta época, muitas empresas adotaram a noção de servidor de aplicações como um host para diversas aplicações diferentes, pois era semelhante a modelos de TI existentes no mundo dos mainframes ( supercomputadores dedicados para processamento de grandes volumes de dados). Uma única equipe de operações seria responsável por controlar, monitorar e manter uma farm de servidores idênticos da Oracle ou da IBM e fazer o deploy (implantação) de diferentes aplicações nessa farm. Essa padronização e consistência era excelente para a equipe de operações e reduziu os custos operacionais em geral. Mas isso criava conflito com os desenvolvedores, pois os ambientes de desenvolvimento e de teste eram grandes, difíceis de criar e precisavam do envolvimento da equipe de operações. Isso frequentemente significava que poderia levar meses até que novos ambientes fossem criados, tornando os projetos mais lentos e aumentando seus custos de desenvolvimento. Além disso, como esses ambientes estavam fora do controle da equipe de desenvolvimento, frequentemente havia inconsistências entre versões dos servidores, dados de aplicativos e instalações de software entre ambientes. O que os desenvolvedores preferiam eram plataformas menores e mais leves geralmente servidores de software livre, como o Tomcat 1 ou o Glassfish 2. Ao mesmo tempo, a complexidade do J2EE estava sendo evitada a favor da suposta simplicidade da plataforma Spring, à medida que técnicas como Inversão de Controle 3 e Injeção de 1 Acessado em 2 Acessado em 3 Nome dado ao padrão de desenvolvimento no qual a sequência (controle) de chamadas dos métodos é invertida em relação à programação tradicional, ou seja, ela não é determinada diretamente pelo programador. Este controle é delegado a uma infraestrutura de software muitas vezes chamada de container ou a qualquer outro componente que possa tomar controle sobre a execução [6]. 15
19 Dependência 4 se tornaram comuns. A lição aprendida com isso foi que as equipes de desenvolvimento descobriram que ter a capacidade de desenvolver e implantar de forma consistente suas próprias aplicações em ambientes de desenvolvimento, teste e produção tão próximos uns aos outros quanto possível não era somente mais rápido, mas menos suscetível a erro, pois classes inteiras de erros decorrentes de inconsistências de ambientes foram eliminadas. Ainda segundo Kyle Brown, essas três observações estão na essência do que Fowler descreve como sendo microsserviços. Um dos princípios da arquitetura de microsserviços de Fowler é que microsserviços são "organizados em torno de capacidades de negócios". A noção completa do padrão Façade estava relacionada à definição de uma API externa específica para um sistema ou subsistema. O resultado disto seria uma API orientada a negócios [5]. Brown também destaca em seu artigo que a regra de Fowler para empregar "endpoints inteligentes e canais burros" se origina da experiência de equipes que, usando EJB, SOAP e outras tecnologias de distribuição complexas, chegaram à conclusão de que tentar fazer um sistema distribuído parecer local sempre era uma escolha ruim. Além disso, os princípios orientadores de Fowler sobre Governança Descentralizada e Gerenciamento de Dados Descentralizado advêm da descoberta de que os programas e ambientes de tempo de execução devem ser autocontidos [5] Monolíticos e Microsserviços Uma das estratégias de Fowler para exemplificar o estilo de microsserviços, foi compará-lo ao estilo monolítico. Tal comparação é demonstrada na Figura 1. 4 É uma forma de Inversão de Controle na qual o container é responsável por injetar em cada componente suas dependências declaradas a fim de manter um baixo nível de acoplamento entre os módulos de um sistema [7]. 16
20 Figura 1. Monolíticos e Microsserviços (adaptado de [3]) Como explícito por Fowler [3], um dos motivos que causam mais frustração entre desenvolvedores, é o fato de que qualquer mudança, seja em uma parte minúscula da aplicação, requer um novo build e deploy da aplicação inteira. Essa frustração contribui muito para a atual crescente migração de aplicações monolíticas para a arquitetura de microsserviços. Além do fato de que os serviços são implantados e escalados de forma independente, há a possibilidade de diferentes serviços serem desenvolvidos em diferentes linguagens de programação e por diferentes equipes de desenvolvedores Características Apesar de nem toda arquitetura de microsserviços possuir necessariamente todas as características comuns a seguir, estas características são vistas como princípios orientadores da arquitetura, que não possui uma definição formal [3]: Componentização via Serviços Um componente é uma unidade de software que pode ser substituída ou atualizada de forma independente das outras unidades. 17
21 Em uma arquitetura de microsserviços pode-se utilizar bibliotecas, mas sua principal forma de componentizar o software é dividi-lo em serviços. Os serviços são componentes que se comunicam por meios como requisições de Web Service ou RPC. Um dos principais motivos para usar serviços como componentes (em vez de bibliotecas) é que os serviços são implantados de maneira independente. Além disso, outra consequência do uso de serviços como componentes é uma interface de componente mais explícita. Organizados em torno de Capacidades de Negócios Ao dividir uma aplicação grande em partes, muitas vezes a gerência se concentra na camada de tecnologia, formando equipes de user interface, back-end e de banco de dados. Em microsserviços, as equipes são multifuncionais, incluindo toda a gama de habilidades necessárias para o desenvolvimento de cada serviço: experiência do usuário, banco de dados e gerenciamento de projetos. Produtos, não Projetos A maioria das abordagens de desenvolvimento de software utilizam um modelo no qual o objetivo é apenas entregar alguma aplicação que seja considerada concluída. Após a conclusão, a aplicação é entregue a uma empresa de manutenção e a equipe de projeto que a construiu é desfeita. Na arquitetura de microsserviços, este modelo é evitado. Em vez disso, cada equipe deve possuir um produto durante toda sua vida útil, ou seja, a equipe assume total responsabilidade pelo software em produção. Endpoints Inteligentes e Canais Burros Ao construir estruturas de comunicação entre diferentes processos, observa-se muitos produtos e abordagens que enfatizam a colocação de inteligência significativa no próprio mecanismo de comunicação. Um bom exemplo disso é o Enterprise Service Bus (ESB), em que os produtos de ESB geralmente incluem instalações sofisticadas para roteamento de mensagens, coreografia, transformação e aplicação de regras de negócios. Aplicações concebidas a partir de microsserviços visam ser tão desacopladas e coesas quanto possível. Recebem uma requisição, executam uma lógica e retornam uma 18
22 resposta. São coreografadas usando protocolo REST simples, em vez de protocolos complexos como, por exemplo, WS-Choreography 5 e WS-BPEL. Equipes de microsserviços usam princípios e protocolos nos quais a rede mundial de computadores é construída. Os protocolos usados mais comumente são o HTTP e os de mensagerias leves, como o AMQP. Muitas vezes, os recursos usados podem ser armazenados em cache com pouco esforço por parte dos desenvolvedores ou responsáveis por operações. A segunda abordagem de uso comum é o envio de mensagens através de um barramento de mensagens leve. A infraestrutura escolhida é tipicamente burra, uma vez que atua somente como um roteador de mensagens, muitas vezes assíncrono. Governança Descentralizada Uma das consequências de uma governança centralizada, é a existência de um conjunto padrão de tecnologias para ser utilizado no desenvolvimento de uma aplicação. Por outro lado, as equipes que criam microsserviços têm a liberdade de escolher o conjunto de tecnologias mais adequado para o desenvolvimento de cada serviço. Além disso, estas equipes preferem a ideia de produzir ferramentas úteis que outros desenvolvedores possam usar para resolver problemas semelhantes aos que estão enfrentando. Com a ascensão do Git 6 e de plataformas como o Github 7 para controle de versão, as práticas de código aberto estão se tornando cada vez mais comuns internamente em empresas. É comum, em microsserviços, a definição do contrato de um serviço ser realizada sob um padrão orientado a consumidor, limitando assim, a necessidade de um gerenciamento de contratos centralizado. Uma das consequências mais marcantes ao possuir uma governança descentralizada é o build it / run it, popularizado pela Amazon, que é o conceito de que a equipe que criou o serviço é responsável por operá-lo 24 horas por dia, 7 dias por semana. Gerenciamento de Dados Descentralizado 5 Acessado em 6 Acessado em 7 Acessado em 19
23 Além de descentralizar decisões sobre modelos conceituais, os microsserviços também descentralizam as decisões de armazenamento de dados. Enquanto as aplicações monolíticas, quase sempre, adotam uma tecnologia de SGBD para persistir os dados em um banco de dados único, os microsserviços permitem que cada serviço gerencie seu próprio banco de dados, sejam instâncias diferentes da mesma tecnologia de banco de dados ou SGBDs totalmente distintos (uma abordagem chamada de persistência poliglota [8]). Embora seja possível usar persistência poliglota em uma aplicação monolítica, ela é muito mais frequente em microsserviços. Esta comparação é ilustrada na Figura 2. Figura 2. Gerenciamento de Dados: Monolíticos e Microsserviços (adaptado de [3]) Automação de Infraestrutura As técnicas de automação de infraestrutura evoluíram muito nos últimos anos a evolução da nuvem e da AWS, em particular, reduziu a complexidade operacional de construir, implantar e operar microsserviços. Muitos dos produtos ou sistemas que estão sendo construídos com microsserviços estão sendo construídos por equipes com ampla experiência em Continuous Delivery e seu precursor, o Continuous Integration. Equipes que constroem software dessa maneira fazem uso extensivo de técnicas de automação de infraestrutura. No cenário de microsserviços, cada serviço possui seu próprio delivery pipeline, que é uma série de ações sequenciais necessárias para a implantação (testes, 20
24 compilação, provisionamento de infraestrutura etc.) que são executadas de forma automática. Projetado para Falha A consequência de utilizar serviços como componentes, é que a aplicação precisa ser projetada para que possa ser tolerante a eventuais falhas de serviços. Dado que os serviços podem falhar a qualquer momento, é importante que haja capacidade de detectar a falha rapidamente e, se possível, restaurar o serviço automaticamente. A fim de verificar comportamentos estranhos e prevenir possíveis falhas, as equipes de microsserviços costumam utilizar sistemas sofisticados de monitoramento de métricas do serviço e visualização de logs, em tempo real. São checados tanto elementos arquiteturais (quantidade de requisições por segundo, por exemplo) quanto de negócios (quantidade de pedidos por minuto, em um e-commerce). Design Evolutivo Quebrar uma aplicação em serviços dá a oportunidade de alterar, substituir e adicionar novos componentes de forma mais simples. Além disso, quando é feita uma mudança na aplicação, enquanto o ambiente monolítico requer que o software seja reimplantado por completo, com microsserviços é necessário apenas que o componente modificado seja reimplantando. Isso simplifica e acelera o processo de implantação Benefícios Abaixo serão listados alguns dos principais benefícios da arquitetura de microsserviços, considerados por Sam Newman [4]: Heterogeneidade Tecnológica Em um sistema composto por múltiplos serviços, cada um pode ser desenvolvido em diferentes tecnologias. Além disso, microsserviços permitem adotar diferentes tecnologias de forma mais fácil e rápida. Em uma arquitetura monolítica, por exemplo, uma das maiores barreiras para adotar novas tecnologias consiste em ter de modificar partes muito grandes do sistema. Isto tem potencial grande para resultar em um impacto negativo, do 21
25 ponto de vista de que se uma dessas partes falharem, possivelmente o sistema inteiro falhará em cascata. Figura 3. Microsserviços permitem adotar diferentes tecnologias facilmente (adaptado de [4]) A Figura 3 ilustra três serviços implementados em linguagens de programação distintas e persistindo os dados em tecnologias de bancos de dados também distintos. Resiliência Se um componente do sistema falhar, esta falha não causará efeito cascata. O problema será isolado e o resto do sistema continuará trabalhando sem esta funcionalidade. Escalabilidade Em um grande serviço monolítico, tudo é escalado junto. Em um grupo de serviços menores, é possível escalar cada serviço o tanto quanto for necessário. 22
26 Figura 4. Escalando cada microsserviço de acordo com sua necessidade (adaptado de [4]) A Figura 4 mostra o exemplo de um sistema que possui três serviços, dentre os quais, o serviço Imagens requer uma quantidade de instâncias em relação aos demais, enquanto Amigos requer apenas duas instâncias para ser mantido estável. Facilidade de Implantação Em uma aplicação monolítica qualquer alteração, por menor que seja, requer a reimplantação da aplicação inteira. Isto pode ser considerado um deployment de alto risco, visto que se algo falhar ou mesmo precisar de um rollback, a aplicação inteira pode ter período de downtime ou demorar para retornar ao estado anterior em pleno ambiente de produção. Com microsserviços, cada serviço é implantado de forma independente. Isto garante que qualquer problema, em determinado serviço, será isolado e não afetará o funcionamento da aplicação. Além disso, a implantação é mais rápida e também agiliza um possível rollback. Alinhamento Organizacional Microsserviços ajudam a diminuir a quantidade de pessoas trabalhando em uma mesma base de código, combinando tamanho de equipe ideal com produtividade. 23
27 2.2 Computação em Nuvem Cloud computing, ou computação em nuvem, é um modelo que permite acesso onipresente, conveniente e sob demanda a um conjunto de recursos de computação configuráveis (redes, servidores, armazenamento, aplicativos e serviços) que podem ser rapidamente provisionados e liberados com esforço mínimo de gerenciamento ou interação com o provedor de serviços [2]. Também pode ser descrita como um modelo de computação que permite ao usuário final acessar uma grande quantidade de aplicações e serviços em qualquer lugar e independentemente da plataforma, bastando para isso ter um terminal conectado à nuvem [9]. A palavra nuvem sugere uma ideia de ambiente desconhecido [...]. Por este motivo, esta foi muito bem empregada na nomenclatura deste novo modelo, na qual toda a infraestrutura e recursos computacionais ficam escondidos [9]. Segundo Garfinkel [10], o professor John McCarthy citou em 1961, na celebração do centenário do MIT, a noção de computação baseada em rede pela primeira vez, embora ele não tenha nomeado o conceito, e muitos acreditam que o termo cloud computing tenha sido proferido pela primeira vez em 2006 pelo então diretor executivo da Google, Eric Schmidt. No ano seguinte, após empresas como Amazon, Microsoft e IBM começarem a investir nesta tecnologia, o termo se popularizou [11]. 24
28 Figura 5. Computação em Nuvem e seus modelos de serviços (adaptado de [12]) A computação em nuvem possui três modelos principais de serviços: Software como Serviço (SaaS), Plataforma como Serviço (PaaS) e Infraestrutura como Serviço (IaaS) [2]. A Figura 5 ilustra a classificação dos tipos mais comuns de serviços de nuvem entre estes três modelos Software como Serviço (SaaS) É o modelo em que o provedor oferece um serviço (software) que pode ser acessado por diversos dispositivos através de uma interface amigável, seja por um navegador web ou por um programa executável. Neste modelo, o consumidor não tem acesso ao controle da infraestrutura (redes, servidores, sistemas operacionais etc.) que sustenta o serviço [2]. Um exemplo deste modelo é o Gmail Plataforma como Serviço (PaaS) 8 Acessado em 25
29 Este é um modelo intermediário, no qual é possível que o desenvolvedor crie e implemente software sem se preocupar com o hardware e outros recursos necessários para executar suas tarefas. [2]. O serviço MongoDB Atlas 9, utilizado mais adiante neste trabalho, exemplifica este modelo Infraestrutura como Serviço (IaaS) De maneira análoga ao SaaS, neste modelo, a infraestrutura é contratada como serviço, ou seja, o desenvolvedor é capaz de provisionar e controlar os recursos de computação fundamentais para rodar seu software [2]. Bons exemplos deste tipo de serviço são o IBM Cloud 10, EC2 da Amazon Web Services 11 e Microsoft Azure Acessado em 10 Acessado em 11 Acessado em 12 Acessado em 26
30 3 Tecnologias Utilizadas Nesta seção, serão brevemente descritas as principais tecnologias utilizadas no desenvolvimento do projeto. 3.1 Golang Go 13 (ou Golang) é uma linguagem de programação de código aberto desenvolvida pela empresa Google sob a licença BSD. Trata-se de uma linguagem imperativa e estruturada, compilada, com tipagem estática e sintaxe simples, muito semelhante à da linguagem C. Também possui garbage collector e é muito eficiente, no sentido de trabalhar muito com poucos recursos. Sua principal vantagem é a simplicidade e eficiência para fazer computação concorrente. 3.2 React React 14 é uma biblioteca JavaScript para desenvolvimento de interface de usuário. Esta biblioteca foi desenvolvida pela empresa Facebook e seu código é aberto sob a licença MIT. Com esta ferramenta é possível desenvolver interfaces gráficas baseadas em componentes que possuem estado e ciclo de vida, simplificando os processos de manutenção/leitura e depuração do código. 3.3 MongoDB O MongoDB 15 é um banco de dados não-relacional open source, baseado em documentos (objetos JSON), altamente escalável e performático. Possui uma query language bastante amigável e é disponibilizado sob a licença GNU AGPLv3. 13 Acessado em 14 Acessado em 27
31 Figura 6. Exemplo da execução de uma query ao MongoDB A Figura 6 demonstra uma query feita ao MongoDB para fazer uma busca na coleção player (jogador), por um jogador pelos atributos competition (competição) e nickname (apelido). Neste exemplo foi utilizado o cliente open source Robo 3T Docker O Docker 17 é uma ferramenta de código aberto distribuída sob a licença Apache 2.0 (ou proprietária, no caso do Docker Enterprise). Trata-se de uma tecnologia que provê uma camada de abstração e automação de virtualização em nível de sistema operacional. Isto permite criar diversos containers, independentes e leves, e rodá-los em uma única máquina, evitando o alto custo de iniciação e manutenção de máquinas virtuais, por exemplo. Container é o encapsulamento da aplicação em um ambiente virtual que contém apenas os ativos necessários para o seu funcionamento. Os contêineres são isolados a nível de disco, memória, processamento e rede. Essa separação permite uma grande flexibilidade, em que ambientes distintos podem coexistir na mesma máquina hospedeira (host), sem causar problemas [13]. 15 Acessado em 16 Acessado em 17 Acessado em 28
32 3.5 Terraform O Terraform 18 é uma tecnologia open source licenciada sob a Mozilla Public License 2.0 pela empresa HashiCorp. Esta tecnologia, descrita como implementações de infraestrutura como código, é útil para fazer provisionamento de infraestrutura automatizado, em diversas plataformas, por meio de um código com sintaxe bastante simples chamado HashiCorp Configuration Language (HCL) ou até mesmo arquivos JSON. Na Figura 7 é possível observar a sintaxe do HCL através de um exemplo de código. Figura 7. Exemplo de código HCL 3.6 GitLab GitLab 19 é um gerenciador de repositórios que utilizam o Git para controle de versão. Apesar de existir um serviço em nuvem, gratuito ou com planos pagos, seu código é aberto e distribuído pela licença MIT. Sua utilidade neste projeto se deve ao fato de que, além de oferecer uma interface amigável e bastante similar à do GitHub, é composto por um sistema de delivery pipeline excelente que é utilizado para fazer integração contínua, por meio de automação dos processos de testes, build e implantação. Este pipeline é configurado de forma bastante simples através de um arquivo YAML. Na Figura 8 é demonstrado um exemplo desta configuração. 18 Acessado em 19 Acessado em 29
33 Figura 8. Exemplo de configuração de um delivery pipeline 3.7 Wrk Wrk 20 é uma ferramenta de benchmark para HTTP, open source, distribuída sob a licença Apache 2.0 modificada. Ela é útil principalmente para a realização de testes de carga/stress devido sua capacidade de manter diversas threads e conexões abertas paralelamente com o intuito de enviar quantidades massivas de requisições. 20 Acessado em 30
34 4 Desenvolvimento do FootBot 4.1 Visão Geral O FootBot é uma aplicação web que calcula probabilidades de resultados de uma partida de futebol. Seu caso de uso é único e simples: consiste de um usuário que fornece os dados de entrada campeonato, time mandante e time visitante e, ao submeter o formulário, as probabilidades então são calculadas e retornadas ao usuário. A fim de prover uma visão, de alto nível de abstração, do funcionamento do sistema, serão apresentados nesta seção o fluxo básico de dados e o algoritmo utilizado para calcular as probabilidades. A Figura 9 demonstra o formulário do cliente web para a entrada dos dados, e a Figura 10 exemplifica uma resposta obtida pelo usuário através deste cliente. Na tela da Figura 9, o usuário escolhe a competição (campo Competition), o time da casa (campo Home Team) e o time visitante (campo Away Team). O usuário clica no botão CALCULATE e o sistema apresenta a tela da Figura 10, que apresenta que o Vasco da Gama tem 51,2% de probabilidade de ganhar, o Botafogo tem 23,9% de probabilidade de sair vitorioso, e a probabilidade de empate é de 24,9%. Em seguinda, são apresentadas as probabilidades de gols da partida, por exemplo, existe a probabilidade de 11,8% do jogo terminar empatado em 1 a 1. 31
35 Figura 9. Tela inicial do FootBot Figura 10. Tela do FootBot de possíveis resultados para uma partida Fluxo de Dados 32
36 O sistema tem o seguinte fluxo de dados. Ao selecionar uma competição (primeiro campo do formulário da Figura 9), uma requisição é feita à API de times, solicitando as equipes pertencentes a esta competição. A resposta é um objeto JSON que contém uma lista de times. Cada um destes times possui uma estrutura de dados conforme exemplificado na Figura 11. Esta lista, então, é utilizada para preencher os dois campos restantes (time mandante e time visitante) para que o usuário faça suas seleções. Figura 11. Estrutura de dados JSON de um time Após a seleção dos dois times, ao clicar no botão do formulário, o usuário submete uma requisição para a API de predição, que retorna um objeto JSON com uma estrutura de dados conforme a exposta na Figura
37 Figura 12. Resposta do cálculo de possíveis resultados da API de predição 34
38 O array que caracteriza o atributo scoreprobs, dos objetos hometeam e awayteam, contém as probabilidades do respectivo time marcar de 0 a 7 gols, na ordem crescente da quantidade de gols. Por exemplo, conforme a Figura 9, o Vasco da Gama jogando em casa contra o Botafogo, tem 27.3% de chance de marcar exatamente um gol. O atributo win configura a probabilidade do respectivo time vencer a partida, por qualquer placar que seja. O atributo draw representa a probabilidade de as equipes empatarem; e a lista de probablescores contém as probabilidades de ocorrer cada placar exato, ordenada pelo placar mais provável até o menos provável Algoritmo A base do algoritmo que calcula as probabilidades de resultados das partidas, é um modelo estatístico frequentemente utilizado por empresas de apostas, principalmente, para essa finalidade. Este modelo é a Distribuição de Poisson, que se aplica a este cenário porque calcula a probabilidade de um evento no caso do FootBot, gols ocorrer exatamente um dado número de vezes (k), dada uma taxa média de ocorrência do evento (λ), caso estes eventos ocorram independentemente de quando ocorreu o último evento [14]. A função então é descrita por: f(k; λ) = e λ λ k, e 2,7183 k! Com isto, a taxa λ é calculada para cada time considerando atributos como seu desempenho (média de gols marcados/concedidos) como mandante ou visitante, média global de gols marcados/concedidos por times mandantes e visitantes na competição, e média de gols dos jogadores escalados para jogar na próxima rodada do campeonato. Com este coeficiente obtido, a função anteriormente descrita é aplicada consecutivamente para k = {0, 1, 2, 3, 4, 5, 6, 7}. Qualquer valor para k > 7 é desconsiderado por ser de ocorrência demasiadamente rara. Assim é obtida a probabilidade para cada valor de k, para cada um dos dois times. 4.3 Microsserviços A fim de se obter diversos web services para realizar uma demonstração de microsserviços no presente trabalho, a arquitetura do FootBot é composta de um serviço para cada domínio que faz parte da aplicação. Os domínios foram definidos empregando o conceito de DDD (Domain-Driven Design), no qual cada domínio caracteriza uma 35
39 parte específica do negócio [15]. Logo, chegou-se aos seguintes domínios (e consequentemente, serviços): Partida (Match), Jogador (Player), Time (Team) e Predição (Prediction). Cada serviço, com exceção do Prediction, consiste de uma API REST, um Worker (aplicação responsável por fazer web crawling e transformação dos dados) que alimenta a base de dados, e um banco de dados não-relacional. O sistema utiliza uma única instância de banco de dados, porém cada serviço possui sua própria coleção independente, ou seja, banco de dados é compartilhado, mas poderiam ser instâncias distintas de SGBDs e diferentes bancos de dados, um para cada domínio. O Prediction é formado por: (i) uma API REST, que realiza chamadas de serviço às demais APIs e, portanto, não possui um banco de dados; e, (ii) um cliente web que consome as APIs e interage com o usuário. É encorajado que cada serviço possua sua linguagem de programação e tecnologia de SGBD. Porém, a fim de exemplificar e por atender bem às necessidades de todos os serviços, optou-se por utilizar Golang para desenvolver todos os web services e MongoDB como tecnologia de SGBD Componentes O diagrama da Figura 13 ilustra o fluxo dos serviços do FootBot. Figura 13. Diagrama de Componentes do FootBot 36
40 Conforme é visto no diagrama da Figura 13, os workers de partidas e times extraem dados do site Soccerway 21, enquanto o de jogadores (da Série A do Campeonato Brasileiro) extrai dados da API pública do CartolaFC Endpoints A Tabela 1, a Tabela 2, a Tabela 3 e a Tabela 4 apresentam a descrição de todos os endpoints expostos por cada API REST. Tabela 1. Endpoints da API Match Endpoint Método Descrição /players/{player-id} GET Retorna os dados do jogador identificado por determinado ID. /competitions/{competition-id}/players GET Retorna todos os jogadores de determinada Endpoint Método Descrição /matches/{match-id} GET Retorna os dados da partida identificada por determinado ID. /competitions/{competition-id}/matches GET Retorna todas as partidas de determinada competição. /competitions/{competition-id}/sides/{sidetype}/score-average GET Retorna a média de gols marcados por mandantes ou visitantes em determinada competição. /competitions/{competition-id}/teams/{teamname}/sides/{side-type}/score-average GET Retorna a média de gols marcados por determinado time em determinada competição atuando como mandante ou visitante. /competitions/{competition-id}/teams/{teamname}/sides/{side-type}/concede-average GET Retorna a média de gols concedidos por determinado time em determinada competição atuando como mandante ou visitante. /competitions/{competition-id}/teams/{teamname}/players /competitions/{competition-id}/teams/{teamname}/score-average 21 Acessado em 22 Acessado em GET GET competição. Tabela 2. Endpoints da API Player Retorna todos os jogadores de determinado time em determinada competição. Retorna a média de gols marcados, por jogadores aptos para jogo, de determinado time em determinada competição. 37
41 Endpoint Método Descrição /teams/{team-id} GET Retorna os dados do time identificado por determinado ID. /competitions/{competition-id}/teams GET Retorna todos os times de determinada competição. Tabela 3. Endpoints da API Team Endpoint Método Descrição /competitions GET Retorna todas as competições disponíveis. /competitions/{competition-id}/hometeam/{home-team-name}/away-team/{awayteam-name}/prediction GET Retorna as probabilidades de resultados de uma partida entre determinados times mandante e visitante em determinada competição. Tabela 4. Endpoints da API Prediction Já os Workers, possuem um único endpoint como apresentado na Tabela 5. Endpoint Método Descrição /build/{competition-id} POST Inicia o processo de crawling de times/partidas/jogadores para determinada competição. Tabela 5. Endpoint dos Workers 4.4 Infraestrutura em Nuvem Nesta seção, são apresentados os principais serviços de computação em nuvem utilizados pelo FootBot. Para este trabalho, foram utilizados apenas serviços e recursos gratuitos. Na AWS 23, por exemplo, durante um ano é possível utilizar vários serviços ainda que com uma série de limites e restrições de forma gratuita. O diagrama de arquitetura da Figura 144 proporciona uma base para melhor compreensão do fluxo destes serviços. Adiante, será explicado o papel de cada serviço nesta arquitetura. 23 Acessado em 38
42 Figura 14. Infraestrutura do FootBot Cloudflare CDN CDN (Content Delivery Network) é uma grande rede de servidores espalhados que armazenam conteúdo de sites em memória e os entrega aos visitantes, conectandoos ao servidor mais próximo e, portanto, reduzindo o tempo de transferência dos dados (latência). A Cloudflare 24 possui inúmeros datacenters distribuídos e oferece um serviço gratuito de CDN. Além disso, este serviço possui mecanismos de segurança como detecção de ataques DDoS (Distributed Denial of Service). Com isto, a maior parte dos acessos sequer chega aos servidores do FootBot, ajudando a garantir uma alta disponibilidade AWS EC2 O EC2 25, ou Elastic Compute Cloud, é um serviço que segue o modelo IaaS, provendo capacidade computacional (servidores) de forma segura e redimensionável. Dentre as vantagens de se utilizar IaaS neste trabalho, destacam-se o custo e a despreocupação com manutenção do hardware. Neste serviço são configuradas, por exemplo, regras de escalonamento automático e load balancing. Para o FootBot são utilizadas instâncias do tipo t2.micro 24 Acessado em 25 Acessado em 39
43 (1 vcpu e 1GB de memória RAM), na região de Ohio Estados Unidos, que são fornecidas gratuitamente durante 750 horas por mês. O escalonamento automático está configurado para utilizar mais duas instâncias sempre que a média de uso de CPU de um grupo estiver acima de 60% por mais de 5 minutos, ou remover duas, em caso da média estar abaixo de 30%, mantendo uma quantidade mínima de quatro instâncias para a aplicação inteira. A Figura 15 apresenta a página inicial do dashboard do EC2, que contém informações como a contabilização dos recursos utilizados e o status de cada zona de disponibilidade da região. Embora esta visão seja para a conta da AWS (e não apenas para o FootBot), todos os recursos consumidos neste caso são do FootBot. Figura 15. Visão geral do dashboard do EC AWS ECS O ECS 26, ou Elastic Container Service, é um serviço de cluster de instâncias com orquestração de containers Docker por padrão. No caso do FootBot, o cluster é composto por quatro instâncias, cada instância é localizada em uma zona de disponibilidade diferente e cada uma roda quatro tasks (imagens Docker) de serviços distintos. Além disso, há duas tasks rodando para cada serviço, cada uma em uma zona diferente, a fim de garantir disponibilidade. Para o usuário, basta configurar o número desejado, além do tipo, de instâncias EC2 e a quantidade de tasks desejada para cada serviço. O balanceamento todo é feito 26 Acessado em 40
44 de forma automática. É possível também configurar regras de escalonamento automático de tasks. A Figura 16 apresenta a página inicial do dashboard do ECS, que contém informações do(s) cluster(s) como quantidade de instâncias e tasks rodando, e utilização de memória e processamento. Note que o serviço Fargate não é utilizado. Figura 16. Visão geral do dashboard do ECS Ao selecionar um cluster, o desenvolvedor é direcionado para uma página como a apresentada na Figura 17. Neste exemplo, está exposta a página de visualização dos serviços do cluster do FootBot. Esta página contém informações como nomes dos serviços, versão das tasks que estão sendo utilizadas para os serviços, quantidade de tasks rodando para cada serviço etc. Observe que é um worker e uma API para os serviços team, match e player, uma API para predictions e um cliente para a as APIs. Ao todo são oito serviços sendo executados. Figura 17. Visualização dos serviços do FootBot no ECS Ainda navegando nesta página, ao clicar na aba ECS Instances, é possível visualizar informações básicas das instâncias ECS presentes no cluster, tais como as 41
45 zonas de disponibilidade, quantidade de tasks rodando em cada instância, quantidade de memória livre etc. Esta seção é demonstrada pela Figura 18. Figura 18. Visualização das instâncias EC2 do cluster no ECS AWS Elastic Load Balancing O Elastic Load Balancing 27 é um serviço que distribui automaticamente o tráfego de aplicativos entre diversos destinos, como instâncias, containers e endereços IP do EC2. Este serviço pode lidar com a carga variável de tráfego dos aplicativos em uma única zona de disponibilidade ou em diversas zonas de disponibilidade. Três tipos de load balancers são oferecidos neste serviço, o tipo utilizado no desenvolvimento deste projeto foi o Application Load Balancer, que faz o roteamento do tráfego na Camada de Aplicação do Modelo OSI (camada 7) utilizando o algoritmo de escalonamento Round-Robin, sendo, portanto, ideal para microsserviços e containers, uma vez que a comunicação destes é feita, quase sempre, por protocolo HTTP AWS Lambda O Lambda 28 é um serviço que oferece a possibilidade de executar um script ou função de maneira instantânea, descartando a necessidade de inicializar uma instância EC2 apenas para realizar este trabalho momentâneo. Para o FootBot, este serviço é utilizado como gatilho para os Workers. Para isso, foi escrita uma função em JavaScript (presente na Figura 366 do Apêndice A) que 27 Acessado em 28 Acessado em 42
46 recebe um objeto JSON como parâmetro contendo dados como o endpoint do Worker e o campeonato AWS CloudWatch O CloudWatch 29 é um serviço que abrange manutenção de logs, alarmes, métricas e criação de eventos. Neste trabalho, foi utilizado a criação de eventos para configurar os momentos em que a execução da função Lambda para ativação dos workers, descrita anteriormente, é acionada. Nesta configuração também é possível inserir um objeto JSON que é passado como entrada para a função Lambda. A Figura 19 mostra os eventos criados para o FootBot no CloudWatch. Figura 19. Visualização das regras de evento do CloudWatch MongoDB Atlas O MongoDB Atlas 30 segue o modelo de PaaS, ou seja, disponibiliza um MongoDB para o desenvolvedor manipular os dados de sua aplicação, além de permitir escalar instâncias de MongoDB de maneira simples e automatizada, na nuvem, sem preocupação com provisionamento de hardware e indisponibilidade. Neste trabalho, foi contratado o serviço pela região de Virginia do Norte Estados Unidos por ser gratuito. A desvantagem disto, é que há um acréscimo de latência devido a distância para os servidores da AWS que estão em Ohio. Além disso, a versão gratuita deste serviço não dá direito a servidor dedicado, o que também pode ocasionar alguma perda de desempenho. 29 Acessado em 30 Acessado em 43
47 5 Resultados Após o desenvolvimento do FootBot, é possível observar que a sua arquitetura permite que novas funcionalidades possam ser adicionadas de forma independente, e que as já existentes possam ser incrementadas com facilidade e organização (adicionar novas competições, por exemplo). Além disso, o objetivo deste capítulo é verificar a assertividade das predições do sistema; validar a disponibilidade e observar o comportamento da infraestrutura sob teste de carga; e validar os benefícios da utilização da camada de CDN. 5.1 Predições Para verificar a assertividade dos resultados calculados pela aplicação, será utilizada como parâmetro a décima rodada da Série A do Campeonato Brasileiro de 2018, encerrada em 06 de junho do respectivo ano, pois foi a época em que este trabalho foi elaborado. As probabilidades obtidas nesta data estão expostas nas figuras 20, 21 e 22. A Figura 23 expõe os resultados reais das partidas ao final da rodada Acessado em 44
48 Figura 20. Probabilidades calculadas pelo FootBot Parte 1 45
49 Figura 21. Probabilidades calculadas pelo FootBot Parte 2 46
50 Figura 22. Probabilidades calculadas pelo FootBot Parte 3 Figura 23. Resultados da 10ª rodada da Série A do Campeonato Brasileiro de 2018 Como o FootBot não fornece uma inferência exata, mas sim probabilidades de resultados, não é correto afirmar que o sistema acertou ou errou algum resultado. Porém, a fim de metrificar a assertividade dos cálculos, foi considerado neste experimento que cada resultado de maior probabilidade (vitória do mandante ou do visitante - win, ou empate - draw) valeu 1 ponto. Desta forma, portanto, o FootBot somou 8 dos 10 pontos possíveis (a partida Corinthians x Santos teve a mesma probabilidade para empate e vitória do Corinthians, neste caso também foi contabilizado 47
51 1 ponto). Além disso, os jogos São Paulo x Internacional, Vitória x Chapecoense e Botafogo x Ceará tiveram seus placares idênticos aos de maiores probabilidades calculadas pela aplicação. 5.2 Teste de Carga Apenas a API de predição foi testada, visto que ela consome todas as demais APIs (que, consequentemente, serão testadas indiretamente) e a aplicação do cliente serve sempre o mesmo conteúdo, estático, que por sua vez fica armazenado tanto no cache do navegador do usuário quanto nos nós da CDN, excluindo assim a necessidade de passar pelo teste. Para testar a performance da API, foi utilizada a ferramenta Wrk (descrita na seção 3.7) rodando em um notebook com processador Intel i5-2410m, 8GB de memória RAM e sistema operacional Arch Linux 64bits. Por limitação da máquina, foi possível rodar os testes com no máximo 25 threads e 1000 conexões HTTP abertas durante 10 segundos. Na Figura 24 e Figura 25, fica evidente que mesmo assim ocorreu uma quantidade ainda que desprezível de erros de conexão. Foi utilizada nos testes, uma variedade de requisições por predições de forma aleatória. Figura 24. Resultado do teste de carga com camada de cache da CDN Figura 25. Resultado do teste de carga diretamente na API 48
52 Observa-se então que, tanto a quantidade de requisições por segundo, quanto a latência e quantidade de timeouts, foram semelhantes nos dois testes e apresentaram números muito satisfatórios, ainda mais tratando-se de um serviço de CDN gratuito (no primeiro teste) e de servidores modestos localizados em Ohio Estados Unidos, agravado ainda pela distância para os servidores do banco de dados, que estão em Virginia do Norte Estados Unidos (segundo teste). Além disso, verifica-se que os testes não foram suficientes para que houvesse a necessidade de escalar a quantidade de instâncias da AWS, uma vez que o máximo de processamento dos servidores que hospedam a API não chegou sequer a 5% da capacidade. A utilização da CPU, conforme o dashboard da AWS, pode ser visto na Figura 26. Figura 26. Taxa de utilização dos processadores durante os testes 5.3 CDN Após a execução de alguns testes consecutivos, foi observado, pelo painel de administração da Cloudflare, que mais de 95% das requisições possuíam resposta armazenada em cache (Figura 27), devido ao repetido acesso a algumas URLs durante os testes. Dessa forma, o tempo de resposta (latência) é otimizado e torna-se possível economizar em servidores e largura de banda (Figura 28). Foi observado também, após dois dias online, que duas ameaças (Figura 29) oriundas da Ucrânia foram bloqueadas, demonstrando assim que este serviço de CDN também provê segurança para a aplicação. 49
53 Figura 27. Gráfico de requisições à Cloudflare Figura 28. Gráficos de performance da Cloudflare Figura 29. Indicadores de segurança da Cloudflare 50