Este é o segundo tutorial de um programa de aprendizado que ensina a modularizar e contentorizar um app monolítico.
O programa de aprendizado consiste nos seguintes tutoriais:
- Visão geral
- Entender o monolítico
- Modularizar o monolítico (este tutorial)
- Preparar o app modular para a criação de contêineres
- Colocar o app modular em um contêiner
- Implantar o app em um cluster do GKE
No tutorial anterior, Entender o monolito, você aprendeu sobre um app monolítico chamado Cymbal Books. Você executou o monólito na sua máquina local e aprendeu que diferentes partes dele se comunicam entre si pelos endpoints.
Neste tutorial, você vai aprender a dividir o monólito em módulos para prepará-lo para a contêinerização. Não é necessário realizar as etapas de modularização porque o código já foi atualizado para você. Sua tarefa é seguir o tutorial e explorar a versão modular do app no repositório para ver como ela difere do monólito original.
Custos
Você pode concluir este tutorial sem custos. No entanto, seguir as etapas do tutorial final desta série gera cobranças na sua conta doGoogle Cloud . Os custos começam quando você ativa o GKE e implanta o app Cymbal Books em um cluster do GKE. Esses 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, desative o GKE ou exclua o projeto depois de concluir este tutorial.
Antes de começar
Antes de iniciar este tutorial, conclua o primeiro tutorial, Entenda o monólito. Neste tutorial, você vai executar a versão modular do Cymbal Books na sua máquina local. Para isso, você precisa ter configurado seu ambiente. Se você já concluiu o primeiro tutorial, clonou um repositório do GitHub. Todas as três versões do app Cymbal Books estão localizadas nesse repositório, dentro das seguintes pastas:
monolith/
modular/
containerized/
Verifique se essas pastas estão na sua máquina antes de continuar. Além disso, verifique se o ambiente virtual book-review-env
está ativo. Se precisar de um lembrete
sobre como ativar, consulte
Criar e ativar um ambiente virtual do
primeiro tutorial. A ativação do ambiente garante que a versão modular
do app tenha tudo o que precisa para ser executada.
O que é modularização?
Neste tutorial, você vai aprender a modularizar o app monolítico para prepará-lo para a contêinerização. A modularização é o processo de transformar um monólito em um app modular. Como você aprendeu no tutorial anterior, a característica distintiva de um monólito é que os componentes dele não podem ser executados ou escalonados de forma independente. Um app modular é diferente: a funcionalidade dele é dividida em módulos que podem ser executados e escalonados de forma independente.
Embora a modularização e a contêinerização sejam feitas juntas com frequência, elas são tratadas como etapas separadas nesta série de tutoriais para ajudar você a entender cada conceito com clareza. Neste tutorial, explicamos como modularizar um monólito. Em um tutorial posterior, vamos explicar como conteinerizar o app modular.
Modularização incremental
Em ambientes de produção, geralmente é feita a modularização de um componente por vez. Você modulariza o componente, integra o módulo ao monólito e garante que tudo funcione antes de trabalhar no próximo componente. Esse estado híbrido, em que alguns componentes são modularizados enquanto outros permanecem parte do monolito, é chamado de microlito. No entanto, neste tutorial, todos os componentes do app são modularizados ao mesmo tempo para fornecer um exemplo completo de como modularizar um app.
Como modularizar o monolítico
Nesta seção, você vai aprender como o monólito da Cymbal Books foi dividido em módulos separados. As etapas são fornecidas para ajudar você a entender o processo de modularização e aplicá-lo aos seus próprios apps. No entanto, não é necessário executar essas etapas neste tutorial porque o repositório clonado já inclui a versão modular do app:
- Identifique as diferentes funções do app
- Criar os módulos
- Ativar a comunicação entre os módulos
- Dê a cada módulo acesso apenas aos dados de que ele precisa
Identifique as diferentes funções do app
A primeira etapa para modularizar o monólito do Cymbal Books é identificar as principais funções dele. No aplicativo de exemplo Cymbal Books, o monólito tem as quatro funções distintas a seguir:
- Como exibir a página inicial
- Detalhes do livro veiculados
- Exibir avaliações de livros
- Veicular imagens de capa de livros
Criar os módulos
Como você viu no tutorial anterior, o monólito é um único app Flask que implementa as quatro funções, identificadas na seção anterior, como gerenciadores de rotas. Para modularizar o app, você pega cada gerenciador de rota e coloca em um app Flask próprio. Em vez de um app Flask com quatro gerenciadores de rota, você tem quatro apps Flask, cada um com um único gerenciador de rota dentro dele.
O diagrama a seguir ilustra essa transformação de um único app Flask em quatro apps Flask separados:
No app modular, cada app Flask é executado de forma independente e fica em uma porta diferente (8080, 8081, 8082, 8083), conforme mostrado no diagrama. Essa configuração é necessária porque, quando você testar o 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: veicular a página inicial e se comunicar com os outros módulos para coletar dados que precisam ser mostrados em uma página da Web. Cada um dos outros módulos se concentra em uma única função: veicular avaliações, detalhes ou imagens. Esses módulos não se comunicam entre si, apenas respondem a solicitações do módulo da página inicial.
Embora o módulo da página inicial tenha uma função de coordenação adicional, o app ainda é verdadeiramente modular porque você pode atualizar qualquer módulo sem afetar os outros. O único aplicativo grande do Flask foi dividido em quatro partes, cada uma delas responsável por uma parte específica da funcionalidade do aplicativo.
Ativar a comunicação entre os módulos
Depois de criar os módulos, a próxima etapa é garantir que eles possam se comunicar
entre si. No app Cymbal Books, essa lógica de comunicação já foi implementada para você. Na pasta modular/
do código baixado,
é possível ver que cada um dos principais recursos do app (servir a página inicial,
detalhes do livro, avaliações e imagens) é implementado como um app Flask separado.
Cada um desses apps define o próprio endpoint HTTP, e os módulos se comunicam enviando
solicitações HTTP para esses endpoints.
Modularizar o monólito do Cymbal Books foi simples. O monólito tem componentes bem definidos que são implementados como gerenciadores de rotas, e cada gerenciador tem um endpoint bem definido. Quando esses manipuladores de rotas são colocados em aplicativos Flask separados, eles mantêm a capacidade de se comunicar pelos endpoints. O ato simples de colocar os gerenciadores de rotas em apps Flask separados cria os módulos e permite que eles se comuniquem.
Uma abordagem comum para a comunicação entre módulos é implementar APIs REST, que permitem que os módulos enviem solicitações HTTP uns aos outros. É assim que funciona no Cymbal Books: cada módulo define endpoints REST usando as ferramentas integradas do Flask. Outra abordagem conhecida é o gRPC, que permite que os módulos chamem as funções uns dos outros diretamente.
Por que a comunicação é simples na Cymbal Books
Cada módulo no app modular é um aplicativo Flask separado que é executado em um servidor da Web. Por exemplo, o módulo da página inicial veicula a página inicial, e o módulo de detalhes do livro veicula os detalhes do livro. A comunicação entre os módulos é simples porque os servidores da Web são projetados para processar solicitações e respostas HTTP. Cada módulo expõe endpoints que outros módulos podem usar para solicitar dados.
Conceda a cada módulo acesso apenas aos dados de que ele precisa
Para modularizar corretamente o monólito, é necessário garantir que cada módulo tenha acesso apenas aos dados de que precisa. Esse princípio, conhecido como isolamento de dados, é um elemento essencial na criação de uma arquitetura verdadeiramente modular.
Um erro comum que as pessoas cometem durante a modularização é permitir que vários módulos acessem os mesmos dados, como um único banco de dados. Esse tipo de implementação cria problemas como os seguintes:
- Acoplamento forte: se a estrutura dos dados compartilhados mudar (por exemplo, uma tabela de banco de dados for renomeada ou uma coluna for adicionada), todos os módulos que dependem desses dados precisarão ser atualizados. A modularização adequada evita esse problema.
- Problemas de tolerância a falhas: quando vários módulos usam a mesma origem de dados, falhas de tempo de execução em um módulo, como consultas inválidas ou tráfego excessivo, podem prejudicar outros módulos. Uma falha em uma parte do sistema pode se propagar para outras partes.
- Gargalos de desempenho: uma única fonte de dados compartilhada pode se tornar um gargalo, o que significa que ela pode diminuir a velocidade de todo o aplicativo quando vários módulos tentam interagir com ela.
Para evitar esses problemas, cada módulo precisa ter a própria fonte de dados.
Se a Cymbal Books tivesse usado um banco de dados para armazenar os dados, seria necessário replicar ou particionar o banco de dados para impor o isolamento de dados e garantir que cada módulo acesse apenas os dados necessários. A replicação envolve a manutenção de cópias separadas do banco de dados para cada módulo, enquanto o particionamento restringe o acesso a tabelas ou linhas específicas. As duas abordagens impedem que os módulos interfiram nos dados uns dos outros.
O diagrama a seguir compara a arquitetura do app de livros monolítico com a arquitetura modular do app de livros:
A implementação do monólito não segue o princípio de isolamento de dados porque as funções dele acessam um único diretório data/
.
Em contraste, o app modular alcança algum grau de isolamento de dados dividindo os dados em diretórios separados e garantindo que cada módulo interaja apenas com os dados designados:
- O módulo de detalhes do livro recebe dados apenas do diretório
details_data/
. - O módulo de avaliações de livros recebe dados apenas do diretório
reviews_data/
. - O módulo de imagens só recebe dados do diretório
images/
.
Em um tutorial posterior, você vai aprender como a contêinerização do app pode melhorar ainda mais o isolamento de dados.
O que você acabou de ver
No setor de desenvolvimento de software, é comum encontrar os termos microsserviços e sistemas distribuídos. Esta seção explica como esses termos se relacionam à implementação modular do Cymbal Books.
Microsserviços
Os microsserviços são módulos autônomos que realizam tarefas específicas. Esses módulos se comunicam com outros módulos por interfaces, como endpoints.
Cada módulo na versão modular do Cymbal Books se encaixa nessa definição e, portanto, pode ser chamado de microsserviço. Quando o app modular é inserido em um contêiner em um tutorial posterior, o código executado dentro de um contêiner também pode ser chamado de microsserviço porque é o mesmo código executado dentro de um módulo.
Sistemas distribuídos
Um sistema distribuído consiste em módulos independentes que se comunicam por uma rede para alcançar um objetivo comum. Esses módulos podem ser executados em máquinas diferentes, mas funcionam juntos como um único sistema.
O app modular Cymbal Books também se encaixa nessa definição: os módulos dele são executados de forma independente e trocam dados por HTTP, mas juntos funcionam como um único sistema. Na próxima seção, você vai executar todos os módulos em uma única máquina para simplificar, mas isso não é obrigatório. Cada módulo pode ser executado em um servidor diferente, e é por isso que a versão modular do app Cymbal Books pode ser classificada como um sistema distribuído.
Testar a implementação modular
Agora que você viu como o monólito do Cymbal Books é transformado em um app modular cujos módulos são apps Flask, é possível testar o aplicativo e ver que cada módulo é executado de forma independente.
Neste tutorial, você executa os módulos na mesma máquina. No entanto, também é possível executar cada módulo em um servidor separado. Como cada módulo é autônomo, ele pode se comunicar com os outros módulos pelos endpoints.
Configurar o ambiente
Siga estas etapas para se preparar para o teste:
No terminal, navegue até o diretório
modular
no repositório clonado:cd modular
Verifique se o ambiente virtual
book-review-env
está ativo. Se você precisar de um lembrete sobre as etapas de ativação, consulte Criar e ativar um ambiente virtual.
Iniciar o app Flask
A pasta /modular
contém um script bash que inicia todos os aplicativos
Flask simultaneamente. Cada módulo do app detecta uma 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 avaliações de livros (book_reviews.py): porta 8082
- App Flask de imagens (images.py): porta 8083
Cada módulo precisa ficar em um número de porta exclusivo porque todos são executados na mesma máquina. Se cada módulo estivesse em um servidor diferente, cada um poderia ficar na mesma porta sem criar conflitos.
Execute o script bash com este comando:
bash ./start_services.sh
O script cria um arquivo de registro separado para cada app Flask (por exemplo,
home.py.log
, book_details.py.log
) para ajudar a identificar problemas de inicialização.
Quando o script for concluído, você verá esta mensagem:
All services have been started. Access the app at http://localhost:8080/
Testar cada app Flask
Teste os módulos acessando os seguintes URLs no navegador:
- Página inicial:
http://localhost:8080/
mostra a página inicial do aplicativo modularizado Cymbal Books. Essa página recupera detalhes, avaliações e imagens de livros fazendo solicitações aos outros módulos. - Detalhes do livro:
http://localhost:8081/book/1
retorna os detalhes do livro com ID 1. Essa resposta são dados JSON que o app formata e mostra de uma maneira mais legível. - Resenhas de livros:
http://localhost:8082/book/1/reviews
busca e retorna as resenhas do livro com ID 1. As avaliações estão no formato JSON. O módulo da página inicial solicita esses dados e os integra à página de detalhes do livro. - Imagens:
http://localhost:8083/images/fungi_frontier.jpg
mostra a imagem da capa do livro Fungi Frontier. Se o URL estiver correto, a imagem vai carregar diretamente no navegador.
Parar os apps Flask
Quando terminar o teste, pare todos os apps Flask com este comando:
kill $(cat home.py.pid book_details.py.pid book_reviews.py.pid images.py.pid)
Resumo
Neste tutorial, mostramos como modularizar o monólito do Cymbal Books. O processo consiste nestas etapas:
- Identificar os componentes distintos do app
- Como criar os módulos
- Garantir que cada módulo tenha acesso apenas aos dados de que precisa
Em seguida, você testou a implementação modular na máquina local.
A seguir
No próximo tutorial, Preparar o app modular para contêinerização, você vai aprender a preparar o app modular para contêinerização atualizando os endpoints para usar nomes de serviço do Kubernetes em vez de localhost
.