Este é o segundo tutorial num percurso de aprendizagem que ensina a modularizar e colocar num contentor uma app monolítica.
O percurso de aprendizagem é composto pelos seguintes tutoriais:
- Overview
- Compreenda o monolito
- Modularize o monolítico (este tutorial)
- Prepare a app modular para a contentorização
- Coloque a app modular em contentores
- Implemente a app num cluster do GKE
No tutorial anterior, Compreender o monolítico, aprendeu sobre uma app monolítica denominada Cymbal Books. Executou o monolítico na sua máquina local e soube que as diferentes partes do monolítico comunicam entre si através dos respetivos pontos finais.
Neste tutorial, vai ver como dividir o monolítico em módulos para o preparar para a contentorização. Não tem de realizar os passos de modularização porque o código já foi atualizado por nós. O seu trabalho consiste em seguir o tutorial e explorar a versão modular da app no repositório para ver as diferenças em relação ao monolítico original.
Custos
Pode concluir este tutorial sem incorrer em custos. No entanto, se seguir os passos no tutorial final desta série, incorre em custos na sua conta doGoogle Cloud . Os custos começam quando ativa o GKE e implementa a app Cymbal Books num cluster do GKE. Estes custos incluem cobranças por cluster do GKE, conforme descrito na página de preços, e cobranças pela execução de VMs do Compute Engine.
Para evitar cobranças desnecessárias, certifique-se de que desativa o GKE ou elimina o projeto assim que concluir este tutorial.
Antes de começar
Antes de começar este tutorial, certifique-se de que concluiu o primeiro tutorial, Compreender o monolítico. Neste tutorial, executa a versão modular do Cymbal Books na sua máquina local. Para isso, tem de ter configurado o seu ambiente. Se já concluiu o primeiro tutorial, clonou um repositório do GitHub. Todas as 3 versões da app Cymbal Books estão localizadas nesse repositório, nas seguintes pastas:
monolith/
modular/
containerized/
Verifique se estas pastas estão no seu computador antes de continuar. Além disso, certifique-se de que o ambiente virtual book-review-env
está ativo. Se precisar de um lembrete
sobre como ativá-lo, consulte o artigo
Crie e ative um ambiente virtual do
primeiro tutorial. A ativação do ambiente garante que a versão modular
da app tem tudo o que precisa para ser executada.
O que é a modularização?
Neste tutorial, vai aprender a modularizar a app monolítica para a preparar para a contentorização. A modularização é o processo de transformar um monólito numa app modular. Como aprendeu no tutorial anterior, a característica distintiva de um monólito é que os respetivos componentes não podem ser executados nem dimensionados de forma independente. Uma app modular é diferente: a respetiva funcionalidade está dividida em módulos que podem ser executados e dimensionados de forma independente.
Embora a modularização e a contentorização sejam frequentemente feitas em conjunto, são tratadas como passos separados nesta série de tutoriais para ajudar a compreender cada conceito claramente. Este tutorial explica como modularizar um monolito e um tutorial posterior explica como colocar a app modular em contentores.
Modularização incremental
Nos ambientes de produção, normalmente, modulariza um componente de cada vez. Modulariza o componente, integra o módulo com o monolítico e certifica-se de que tudo funciona antes de trabalhar no componente seguinte. Este estado híbrido, em que alguns componentes são modularizados enquanto outros permanecem parte do monolítico, é denominado microlítico. No entanto, neste tutorial, todos os componentes da app são modularizados ao mesmo tempo para fornecer um exemplo completo de como modularizar uma app.
Como modularizar o monolítico
Nesta secção, vai aprender como o monolítico da Cymbal Books foi dividido em módulos separados. São fornecidos passos para ajudar a compreender o processo de modularização, para que possa aplicá-lo às suas próprias apps. No entanto, não precisa de realizar estes passos neste tutorial porque o repositório clonado já inclui a versão modular da app:
- Identifique as funções distintas da app
- Crie os módulos
- Ative a comunicação entre os módulos
- Conceda a cada módulo acesso apenas aos dados de que precisa
Identifique as funções distintas da app
O primeiro passo para modularizar o monolítico da Cymbal Books é identificar as suas principais funções. Na aplicação de exemplo Cymbal Books, o monólito tem as seguintes quatro funções distintas:
- Publicar a página inicial
- Apresentação dos detalhes do livro
- Apresentação de críticas de livros
- Publicação de imagens de capas de livros
Crie os módulos
Como viu no tutorial anterior, o monolítico é uma única app Flask que implementa as quatro funções, que foram identificadas na secção anterior, como controladores de rotas. Para modularizar a app, pega em cada controlador de rotas e coloca-o na sua própria app Flask. Em vez de uma app Flask com quatro controladores de rotas, tem quatro apps Flask, cada uma com um único controlador de rotas no respetivo interior.
O diagrama seguinte ilustra esta transformação de uma única app Flask em quatro apps Flask separadas:
Na app modular, cada app Flask é executada de forma independente e ouve numa porta diferente (8080, 8081, 8082, 8083), conforme mostrado no diagrama. Esta configuração é necessária porque, quando testar a app modular mais tarde neste tutorial, vai executar todos os módulos na mesma máquina. Cada app precisa de um número de porta diferente para evitar conflitos.
O módulo da página inicial tem duas responsabilidades: apresenta a página inicial e comunica com os outros módulos para recolher dados que têm de ser apresentados numa página Web. Cada um dos outros módulos está focado numa única função: publicar críticas, detalhes ou imagens. Estes módulos não comunicam entre si. Apenas respondem a pedidos do módulo da página inicial.
Embora o módulo da página inicial tenha uma função de coordenação adicional, a app continua a ser verdadeiramente modular porque pode atualizar qualquer módulo sem afetar os outros módulos. A única aplicação Flask grande foi dividida em quatro partes, cada uma das quais processa uma parte específica da funcionalidade da aplicação.
Ativar a comunicação entre os módulos
Depois de criar os módulos, o passo seguinte é garantir que estes conseguem comunicar
entre si. Na app Cymbal Books, esta lógica de comunicação já foi
implementada para si. Na pasta modular/
do código que transferiu,
pode ver que cada uma das principais funcionalidades da app, como a apresentação da página inicial, os detalhes dos livros, as críticas e as imagens, é implementada como uma app Flask separada.
Cada uma destas apps define o seu próprio ponto final HTTP e os módulos comunicam através do
envio de pedidos HTTP para esses pontos finais.
A modularização do monolito da Cymbal Books foi simples. O monolítico tem componentes bem definidos que são implementados como controladores de rotas, e cada controlador de rotas tem um ponto final bem definido. Quando estes controladores de rotas são colocados em aplicações Flask separadas, mantêm a capacidade de comunicar através dos respetivos pontos finais. O ato simples de colocar os controladores de rotas em apps Flask separadas cria os módulos e permite que os módulos comuniquem entre si.
Uma abordagem comum para a comunicação entre módulos é implementar APIs REST, que permitem que os módulos enviem pedidos HTTP uns aos outros. É assim que funciona no Cymbal Books: cada módulo define pontos finais REST usando as ferramentas incorporadas do Flask. Outra abordagem popular é o gRPC, que permite que os módulos chamem as funções uns dos outros diretamente.
Por que motivo a comunicação é simples no Cymbal Books
Cada módulo na app modular é uma aplicação Flask separada que é executada num servidor Web. Por exemplo, o módulo da página inicial apresenta a página inicial e o módulo de detalhes do livro apresenta os detalhes do livro. A comunicação entre os módulos é simples porque os servidores Web são concebidos para processar pedidos e respostas HTTP. Cada módulo expõe pontos finais que outros módulos podem usar para pedir dados.
Conceda a cada módulo acesso apenas aos dados de que necessita
Para modularizar corretamente o monolítico, tem de garantir que cada módulo tem acesso apenas aos dados de que precisa. Este princípio, conhecido como isolamento de dados, é um elemento crítico na criação de uma arquitetura verdadeiramente modular.
Um erro frequente que as pessoas cometem durante a modularização é permitir que vários módulos acedam aos mesmos dados, como uma única base de dados. Este tipo de implementação cria problemas, como os seguintes:
- Acoplamento forte: se a estrutura dos dados partilhados for alterada, por exemplo, se o nome de uma tabela da base de dados for alterado ou se for adicionada uma coluna, todos os módulos que dependem desses dados têm de ser atualizados. A modularização adequada evita este problema.
- Problemas de tolerância a falhas: quando vários módulos usam a mesma origem de dados, as falhas de tempo de execução num módulo, como consultas inválidas ou tráfego excessivo, podem interromper outros módulos. Uma falha numa parte do sistema pode provocar falhas noutras partes do sistema.
- Gargalos de desempenho: uma única origem de dados partilhada pode tornar-se um gargalo, o que significa que pode abrandar toda a aplicação quando vários módulos tentam interagir com ela.
Para evitar estes problemas, cada módulo deve ter a sua própria origem de dados.
Se a Cymbal Books tivesse usado uma base de dados para armazenar os respetivos dados, teria de replicar ou dividir a base de dados para aplicar o isolamento de dados e garantir que cada módulo acede apenas aos dados de que precisa. A replicação envolve a manutenção de cópias separadas da base de dados para cada módulo, enquanto a partição restringe o acesso a tabelas ou linhas específicas. Ambas as abordagens impedem que os módulos interfiram nos dados uns dos outros.
O diagrama seguinte compara a arquitetura da app de livros monolítica com a arquitetura modular da app de livros:
A implementação do monólito não segue o princípio do isolamento de dados, uma vez que as funções do monólito acedem a um único diretório data/
.
Por outro lado, a app modular alcança algum grau de isolamento de dados dividindo os dados em diretórios separados e garantindo que cada módulo interage apenas com os respetivos dados designados:
- O módulo de detalhes do livro obtém dados apenas do diretório
details_data/
. - O módulo de críticas de livros obtém dados apenas do diretório
reviews_data/
. - O módulo de imagens obtém dados apenas do diretório
images/
.
Num tutorial posterior, vê como a contentorização da app pode melhorar ainda mais o isolamento de dados.
O que acabou de ver
Na indústria de programação de software, encontra frequentemente os termos microsserviços e sistemas distribuídos. Esta secção explica como estes termos se relacionam com a implementação modular do Cymbal Books.
Microsserviços
Os microsserviços são módulos autónomos que realizam tarefas específicas. Estes módulos comunicam com outros módulos através de interfaces, como pontos finais.
Cada módulo na versão modular do Cymbal Books enquadra-se nesta definição e, por isso, pode ser denominado um microsserviço. Quando a app modular é colocada num contentor num tutorial posterior, o código executado num contentor também pode ser denominado microsserviço, porque é o mesmo código executado num módulo.
Sistemas distribuídos
Um sistema distribuído consiste em módulos independentes que comunicam através de uma rede para alcançar um objetivo comum. Estes módulos podem ser executados em máquinas diferentes, mas funcionam em conjunto como um único sistema.
A app modular Cymbal Books também se enquadra nesta definição: os respetivos módulos são executados de forma independente e trocam dados através de HTTP, mas, em conjunto, funcionam como um único sistema. Na secção seguinte, vai executar todos os módulos numa única máquina para simplificar, mas não é obrigatório. Cada módulo pode ser executado com a mesma facilidade num servidor diferente, motivo pelo qual a versão modular da app Cymbal Books pode ser classificada como um sistema distribuído.
Teste a implementação modular
Agora que viu como o monolito do Cymbal Books é transformado numa app modular cujos módulos são apps Flask, pode testar a aplicação e ver que cada módulo é executado de forma independente.
Neste tutorial, executa os módulos na mesma máquina. No entanto, também pode executar cada módulo num servidor separado. Uma vez que cada módulo é autónomo, pode comunicar com os outros módulos através dos respetivos pontos finais.
Configure o seu ambiente
Siga estes passos para se preparar para os testes:
No terminal, navegue para o diretório
modular
no repositório clonado:cd modular
Certifique-se de que o ambiente virtual
book-review-env
está ativo. Se precisar de um lembrete sobre os passos de ativação, consulte o artigo Crie e ative um ambiente virtual.
Inicie a app Flask
A pasta /modular
contém um script bash que inicia todas as aplicações Flask simultaneamente. Cada módulo da app escuta numa porta exclusiva, como 8080 ou 8081:
- App Flask da página inicial (home.py): porta 8080
- App Flask de detalhes do livro (book_details.py): porta 8081
- App Flask de críticas literárias (book_reviews.py): porta 8082
- App Flask de imagens (images.py): porta 8083
Cada módulo tem de ouvir num número de porta exclusivo porque todos os módulos são executados no mesmo computador. Se cada módulo estivesse num servidor diferente, cada um podia ouvir o mesmo número de porta sem criar conflitos de portas.
Execute o script bash com este comando:
bash ./start_services.sh
O script cria um ficheiro de registo separado para cada app Flask (por exemplo, home.py.log
e book_details.py.log
) para ajudar a identificar problemas de arranque.
Quando o script é concluído com êxito, é apresentada esta mensagem:
All services have been started. Access the app at http://localhost:8080/
Teste cada app Flask
Teste os módulos visitando os seguintes URLs no seu navegador:
- Página inicial:
http://localhost:8080/
apresenta a página inicial da aplicação Cymbal Books modularizada. Esta página obtém detalhes do livro, críticas e imagens através de pedidos aos outros módulos. - Detalhes do livro:
http://localhost:8081/book/1
devolve os detalhes do livro com o ID 1. Esta resposta são dados JSON que a app formata e apresenta de uma forma mais legível. - Críticas literárias:
http://localhost:8082/book/1/reviews
obtém e devolve as críticas do livro com o ID 1. As críticas estão no formato JSON. O módulo da página inicial pede estes dados e integra-os na página de detalhes do livro. - Imagens:
http://localhost:8083/images/fungi_frontier.jpg
apresenta a imagem da capa do livro Fungi Frontier. Se o URL estiver correto, a imagem deve ser carregada diretamente no navegador.
Pare as apps Flask
Quando terminar os testes, pare todas as apps Flask com este comando:
kill $(cat home.py.pid book_details.py.pid book_reviews.py.pid images.py.pid)
Resumo
Este tutorial mostrou-lhe como modularizar o monolítico Cymbal Books. O processo consiste nestes passos:
- Identificar os componentes distintos da app
- Criar os módulos
- Garantir que cada módulo tem acesso apenas aos dados de que precisa
Em seguida, testou a implementação modular na sua máquina local.
O que se segue?
No próximo tutorial, Prepare a app modular para a contentorização, vai aprender a preparar a app modular para a contentorização atualizando os pontos finais para usar nomes de serviços do Kubernetes em vez de localhost
.