Como migrar um aplicativo monolítico para microsserviços no Google Kubernetes Engine

Neste artigo, você conhecerá os conceitos gerais e abstratos envolvidos na migração de um site de uma plataforma monolítica para uma plataforma de microsserviços refatorada e baseada em contêineres no Google Cloud Platform (GCP). A migração é feita recurso a recurso para evitar um evento de migração em grande escala e os riscos associados. Este artigo é destinado a profissionais de TI responsáveis por um site complexo hospedado em uma plataforma monolítica que eles querem modernizar. A leitura deste conteúdo não requer um conhecimento profundo do GCP ou do Kubernetes.

O objetivo de uma migração desse tipo é fornecer um ambiente mais ágil e escalonável para recursos individuais do site. No novo local, fica mais fácil gerenciar e atualizar esses recursos em comparação com uma plataforma monolítica. Executar o site nesse tipo de ambiente resulta em melhorias mais rápidas em cada recurso migrado, proporcionando aos usuários mais valor ao longo do tempo.

Como exemplo de carga de trabalho, são usados neste artigo sites de comércio eletrônico. Muitos sites desse tipo são criados com plataformas monolíticas e proprietárias. Isso faz deles bons candidatos para a migração descrita aqui. No entanto, é possível aplicar os princípios descritos neste artigo a uma ampla variedade de cargas de trabalho. Os princípios abordados neste artigo podem ser aproveitados em outras situações, desde que os sistemas e restrições sejam semelhantes o suficiente aos aqui descritos. Por exemplo, sites de reserva de hotéis ou aluguel de carros também são bons candidatos para esse padrão de migração.

Conforme descrito no documento Padrões e práticas de implementações híbridas e em várias nuvens, há três padrões principais de migração para a nuvem: lift-and-shift, transformar e mover e remover e substituir. Neste artigo, há a descrição de uma variante específica do padrão do tipo remover e substituir. Nessa variante, o padrão é aplicado de modo incremental a cada recurso, em vez de ao aplicativo como um todo.

Além desse padrão de migração, dois padrões híbridos são explorados neste artigo. Durante a migração, o aplicativo assume uma arquitetura híbrida em que alguns recursos estão na nuvem e outros ainda estão no ambiente local. Após a conclusão da migração, o aplicativo inteiro fica hospedado na nuvem, mas ainda interage com os serviços de back-end que permanecem no ambiente local.

Terminologia

aplicativo
Neste artigo, um aplicativo é um sistema de software completo, possivelmente com muitos recursos, que é visto como uma única unidade pelos usuários finais. Por exemplo, um site de comércio eletrônico é um aplicativo. Tudo o que pode ser realizado em um aplicativo é feito com um recurso (ou funcionalidade) específico desse aplicativo.
recurso
Uma unidade de funcionalidade de um aplicativo. Os recursos podem ser voltados ao usuário e essenciais para o aplicativo (como o carrinho de compras em um site de comércio eletrônico), voltados ao usuário e exigidos pelo aplicativo (como o login) ou internos do aplicativo (como o gerenciamento de estoque em um site de comércio eletrônico).
serviço
Um componente independente de um aplicativo. Neste artigo, um aplicativo é composto por serviços diferentes que não são exibidos aos usuários finais. Por exemplo, um banco de dados usado por um site é um serviço.
aplicativo monolítico
Um aplicativo criado como uma única unidade implantável, também conhecido simplesmente como um monolítico. Exemplos incluem um único aplicativo Java EE (em inglês) ou um único aplicativo da Web .NET. Um aplicativo monolítico geralmente é associado a um banco de dados e a uma interface de usuário voltada para o cliente.
microsserviço
Um único serviço criado para acomodar um recurso do aplicativo. No padrão de microsserviços, o aplicativo é um agregado de vários serviços, cada um com uma finalidade específica. Por exemplo, é possível ter um serviço que lida com o carrinho de compras dos clientes, outro que processa o serviço de pagamento e um terceiro que interage com um aplicativo de back-end para controlar o estoque. Esses microsserviços são fracamente acoplados e interagem uns com os outros por meio de APIs bem definidas. Eles podem ser escritos em linguagens e frameworks diferentes e ter ciclos de vida distintos.
arquitetura híbrida
Uma arquitetura que combina um provedor de nuvem pública, como o GCP, com recursos privados hospedados no seu próprio data center. Há muitos motivos e maneiras de implementar uma arquitetura híbrida. Tudo isso está descrito no artigo Padrões e práticas de implementações híbridas e em várias nuvens.
serviços sem e com estado
Uma indicação sobre se um serviço gerencia diretamente o armazenamento de dados. Neste artigo, é adotada a mesma definição de "sem estado" e "com estado" da metodologia de aplicação doze-fatores. Um serviço é sem estado quando não depende de nenhum dado para funcionar. Um serviço com estado é o oposto. Por exemplo, um serviço que processa os carrinhos de compras dos clientes é com estado porque os carrinhos de compras precisam ser armazenados e recuperados. Um serviço que verifica a disponibilidade de itens no sistema de back-end é sem estado porque os dados (estado) são armazenados pelo sistema de back-end, e não pelo serviço.

Por que migrar para microsserviços?

Desmembrar um aplicativo em microsserviços tem as seguintes vantagens, sendo que a maioria deriva do fato de que os microsserviços são levemente acoplados:

  • É possível testar e implantar os microsserviços independentemente. Quanto menor for a unidade a ser implantada, mais fácil será o processo.
  • É possível implementá-los em linguagens e frameworks diferentes. Você tem a liberdade de escolher a melhor tecnologia para seu caso de uso específico em cada microsserviço.
  • Eles podem ser gerenciados por equipes diferentes. O limite entre microsserviços facilita a dedicação de uma equipe a um ou vários deles.
  • Ao migrar para microsserviços, você atenua as dependências entre equipes. Cada equipe passa a se preocupar apenas com as APIs dos microsserviços de que dependem. Elas não precisam pensar sobre como os microsserviços são implementados, os ciclos de lançamento e outros fatores.
  • É mais fácil planejar o que acontecerá no caso de falhas. Como há limites claros entre os serviços, é mais fácil determinar o que fazer se um serviço ficar inativo.

Os microsserviços têm algumas desvantagens em comparação aos monolíticos:

  • Como um aplicativo baseado em microsserviço é uma rede de serviços diferentes que geralmente interagem de maneiras que não são óbvias, a complexidade geral do sistema tende a aumentar.
  • Diferentemente dos componentes internos de um monolítico, os microsserviços se comunicam por meio de uma rede. Em algumas circunstâncias, isso pode ser visto como uma preocupação de segurança. O Istio soluciona esse problema ao criptografar automaticamente o tráfego entre microsserviços.
  • Pode ser difícil alcançar o mesmo nível de desempenho de uma abordagem monolítica devido às latências entre os serviços.
  • O comportamento do seu sistema não é causado por um único serviço, mas por muitos e pelas interações entre eles. Por isso, entender como o sistema se comporta na produção (a capacidade de observação) é mais difícil. O Istio também é uma solução para esse problema.

Enquanto algumas empresas, como o Google, usam microsserviços há muitos anos, o conceito, e sua relação com a arquitetura orientada a serviços (SOA, na sigla em inglês), foi formalizado por James Lewis, Martin Fowler e Sam Newman no artigo Microsserviços (em inglês).

Visão geral do processo de migração

O processo de migração descrito neste artigo é longo e pode levar meses para ser concluído porque é um projeto de grande escala. Esta seção traz o mapeamento da transição de um aplicativo monolítico em um ambiente local para um aplicativo totalmente hospedado no GCP e construído com microsserviços.

O ponto de partida: um aplicativo monolítico em ambiente local

Neste artigo, pressupõe-se que você atualmente executa um aplicativo monolítico em um ambiente local. O diagrama da arquitetura geral abaixo provavelmente é semelhante à sua arquitetura atual.

Arquitetura de um aplicativo monolítico típico

Esse diagrama não é uma representação completa dos seus sistemas atuais. Veja a seguir algumas das tecnologias normalmente encontradas em uma arquitetura como essa:

  • Bancos de dados relacionais, como Oracle® ou SAP HANA
  • Plataformas de comércio eletrônico, como Oracle ATG ou o SAP Hybris
  • Apache Solr ou outros mecanismos de pesquisa

A linha de chegada: um aplicativo baseado em microsserviços no GCP

O processo abordado neste documento descreve a migração de uma arquitetura monolítica local para uma baseada em microsserviços e executada no GCP. A arquitetura final é descrita em Cargas de trabalho de comércio escalonáveis usando microsserviços. Esta é a aparência dela:

Arquitetura após a migração para contêineres e o GKE

Na arquitetura final, os microsserviços são executados no Google Kubernetes Engine (GKE). O Kubernetes é uma plataforma para gerenciar, hospedar, escalonar e implantar contêineres. Os contêineres são uma maneira portátil de empacotar e executar um código. Eles são ideais para o padrão de microsserviços, em que cada microsserviço pode ser executado em um contêiner próprio. Os microsserviços podem fazer chamadas para os sistemas de back-end por meio de uma conexão de rede privada criada pelo Cloud Interconnect ou pelo Cloud VPN. Como alternativa, é possível usar o Apigee para expor os serviços de back-end e proteger o acesso a eles. Mais informações sobre esses produtos e como escolher o ideal para você estão descritas mais adiante neste documento, na seção Apigee, Cloud VPN e Cloud Interconnect.

Os microsserviços também podem interagir com vários outros produtos do GCP, dependendo das necessidades deles. O Cloud Storage e o Cloud SQL são dois dos produtos mais comuns do GCP usados em um aplicativo de comércio eletrônico. O Cloud Pub/Sub pode ser usado como um barramento de mensagens entre microsserviços diferentes para o trabalho assíncrono.

É possível expor o aplicativo à Internet de duas maneiras: diretamente por meio de um balanceador de carga do GCP para recursos como imagens e, opcionalmente, por meio do Apigee para APIs públicas.

Nas tabelas a seguir você verá os produtos que podem ser usados na arquitetura final. Nem todos são obrigatórios, e empregá-los depende do caso de uso exato.

Rede

Produto do GCP Uso Observações
Nuvem privada virtual VPC é uma rede privada definida por software onde é possível encontrar recursos como um cluster do GKE. Nela, estão incluídos recursos como firewall e roteamento. Há uma VPC disponível globalmente, o que permite a conectividade privada em todo o mundo por meio de redes de fibra do Google. O Cloud VPC é obrigatório para essa arquitetura.
Cloud Interconnect O Cloud Interconnect estende a rede local para a rede do Google por meio de uma conexão altamente disponível e de baixa latência. Para se conectar ao Google, é possível fazer isso diretamente com a Interconexão dedicada ou por meio de um provedor de serviços autorizado com o Partner Interconnect. Seu site de comércio eletrônico provavelmente precisa chamar serviços de back-end no ambiente local, como um sistema de faturamento ou de gerenciamento de armazém.
O Cloud Interconnect é uma das soluções para isso.
Cloud VPN O Cloud VPN estende a rede local para a rede do Google com segurança por meio de um túnel de uma VPN IPsec. O tráfego é criptografado e viaja entre as duas redes pela Internet pública. O Cloud VPN é útil para conexões de dados de baixo volume. Seu site de comércio eletrônico provavelmente precisa chamar serviços de back-end no ambiente local, como um sistema de faturamento ou de gerenciamento de armazém.
O Cloud VPN é uma das soluções para isso.
Cloud Load Balancing O Cloud Load Balancing é uma solução gerenciada de balanceamento de carga do Google. Ele é compatível com balanceamento de carga L4 (TCP/UDP) e L7 (HTTP). Ele também pode ser usado como um endpoint de terminação SSL (HTTPS). Ao criar um balanceador de carga do GCP, você terá um único IP anycast. Todos os usuários que tentarem acessar esse IP serão encaminhados automaticamente para o ponto de presença do Google mais próximo para reduzir a latência da rede, graças à rede nível Premium do Google. O Cloud Load Balancing é obrigatório para essa arquitetura.
Cloud CDN O Cloud CDN, uma rede de fornecimento de conteúdo, usa os principais pontos de presença distribuídos globalmente do Google para armazenar em cache o conteúdo com balanceamento de carga HTTP(S) próximo aos usuários. O armazenamento de conteúdo em cache nas bordas da rede do Google proporciona aos usuários mais rapidez no fornecimento de conteúdo e custos de veiculação menores. O Cloud CDN não é obrigatório nesse cenário, mas é recomendado, principalmente para conteúdo estático.

Plataforma

Produto do GCP Uso Observações
Google Kubernetes Engine (GKE) O GKE é o produto de Kubernetes gerenciado do Google para a implantação de aplicativos em contêineres. O GKE é totalmente compatível com o Kubernetes de código aberto e fornece muitos recursos avançados, como clusters regionais para alta disponibilidade, clusters privados, escalonamento automático de pod vertical, escalonamento automático de cluster, GPUs e nós preemptivos. O GKE é obrigatório para essa arquitetura.
Istio O Istio reduz a complexidade do gerenciamento de implantações de microsserviços ao oferecer uma maneira uniforme de proteger, conectar e monitorar os microsserviços. O Istio não é obrigatório para essa arquitetura, mas fornece recursos úteis, como monitoramento aprimorado, criptografia do tráfego e roteamento, bem como injeção de falhas para testar a resiliência do aplicativo.
Apigee A Apigee é um gateway de APIs gerenciado. Ao usar a Apigee, é possível projetar, publicar, monitorar e monetizar APIs com segurança.
Use a Apigee para expor APIs públicas e privadas. Em uma arquitetura de microsserviços, as APIs públicas são hospedadas no GCP, enquanto os sistemas locais de back-end podem ser expostos como APIs privadas que são consumidas apenas por microsserviços no GCP.
A Apigee não é obrigatória para essa arquitetura, mas recomenda-se que todo o conteúdo do seu site seja exibido por APIs públicas. Um gateway de APIs, como a Apigee, oferece muitos recursos para gerenciamento de APIs, como cotas, controle de versão e autenticação.
Cloud Pub/Sub O Cloud Pub/Sub é um sistema de mensagens e streaming. Se for usado nessa arquitetura, ele funciona como um barramento de mensagens entre microsserviços, o que permite fluxos de trabalho assíncronos entre eles. O Cloud Pub/Sub não é obrigatório. No entanto, o padrão de editor/inscrito pode ajudar a reduzir o número de problemas de escalonamento.

Storage

Produto do GCP Uso Observações
Cloud Storage O Cloud Storage fornece uma API de armazenamento de objetos unificada. Ele é adequado para muitos casos de uso, como exibir conteúdo de sites, fazer backup e arquivar dados e distribuir objetos grandes. No caso de um site de comércio eletrônico, o principal uso do Cloud Storage é armazenar e exibir recursos estáticos, como vídeos e imagens de produtos. A escalonabilidade perfeita do Cloud Storage, juntamente com o Cloud CDN, o torna um bom candidato para a arquitetura de microsserviços descrita neste documento. Por isso, ele é recomendado.
Cloud Firestore O Cloud Firestore é um banco de dados de documentos NoSQL rápido e totalmente gerenciado. O Cloud Firestore não é obrigatório para essa arquitetura, mas é ideal para vários casos de uso comuns em sites de comércio eletrônico. Por exemplo, é possível usá-lo para armazenar metadados de usuários e carrinhos de compras.
Cloud SQL O Cloud SQL é um produto gerenciado do Google para MySQL e PostgreSQL. Esses bancos de dados relacionais têm uma ampla variedade de usos. O Cloud SQL não é obrigatório nesse cenário, mas é ideal para vários casos de uso comuns em sites de comércio eletrônico. Por exemplo, é possível usar o Cloud SQL para armazenar pedidos, facilitando a realização de agregação e cálculos.
Cloud Spanner O Cloud Spanner é um banco de dados relacional disponível globalmente, escalonável horizontalmente e de forte consistência. Com um SLA de tempo de atividade de 99,999% (para instâncias multirregionais), ele garante uma disponibilidade muito alta para dados essenciais ao negócio. O Cloud Spanner não é obrigatório nesse cenário. Por ser um banco de dados relacional que oferece consistência transacional em escala global, o Cloud Spanner é ideal para sites de comércio eletrônico que atendem a um público internacional.
Cloud Memorystore O Cloud Memorystore para Redis é uma versão gerenciada do Redis, um banco de dados de chave-valor em memória. Como um banco de dados de baixa latência, o Redis é ideal para dados acessados com muita frequência. O Cloud Memorystore não é obrigatório nesse cenário. No entanto, ele é ideal para vários casos de uso comuns em sites, como o armazenamento de informações de sessões de usuários e o fornecimento de cache de aplicativos.

Também é possível usar outros produtos do GCP, mas a lista acima representa os mais utilizados em uma arquitetura de comércio eletrônico. Lembre-se também de que uma evolução natural dessa arquitetura é adicionar componentes para adquirir conhecimento a partir dos dados por meio do uso de produtos como Cloud Bigtable, BigQuery, Cloud AutoML e AI Platform.

Continue usando algumas das suas tecnologias atuais nessa arquitetura final se elas ainda forem relevantes para você ou se o custo de migração delas for muito alto. Veja alguns exemplos de como executar tecnologias comuns de comércio eletrônico no GCP:

Apigee, Cloud VPN e Cloud Interconnect

Uma das decisões mais importantes a tomar no início do projeto é como lidar com a comunicação entre os novos microsserviços hospedados no GKE e o sistema legado local. Há duas soluções principais que podem coexistir: comunicação baseada em APIs ou comunicação baseada em uma conexão privada.

Na comunicação baseada em APIs, usa-se uma solução de gerenciamento de APIs, como a Apigee, como um proxy entre os dois ambientes. Isso permite ter um controle preciso sobre como e quais partes dos sistemas legados serão expostas. Ele também permite refazer a implementação de uma API sem gerar impacto (ou seja, migrar de um serviço legado para um microsserviço) sem afetar os consumidores da API. O diagrama a seguir mostra as interações entre o Apigee, seus sistemas locais e seus sistemas do GCP.

Apigee como proxy na frente de uma combinação de sistemas locais e baseados no GCP

O artigo Padrões para implantar APIs do Kubernetes em escala com o Apigee e o e-book da Apigee Além da arquitetura ESB com APIs (em inglês) podem ajudar você na elaboração desse projeto.

Na solução baseada em conectividade privada, você se conecta aos ambientes locais e do GCP usando uma conexão de rede privada. Os microsserviços se comunicam com os sistemas legados por meio dessa conexão. É possível configurar túneis de VPN baseados em IPSec com o Cloud VPN. Para atender às necessidades de uma largura de banda maior, o Cloud Interconnect fornece uma conexão altamente disponível e de baixa latência. Consulte Escolher um tipo de interconexão para ter uma visão geral das diferentes opções.

O diagrama a seguir mostra as interações entre os sistemas locais e do GCP com o uso do Cloud VPN ou do Cloud Interconnect.

Cloud Interconnect ou Cloud VPN conectando um sistema local e um sistema baseado no GCP

A solução baseada em APIs é implementada pelas equipes responsáveis pelos aplicativos. Ela requer uma maior integração desde o início do projeto com o aplicativo legado do que a solução baseada em conectividade privada. Entretanto, a solução baseada em APIs oferece mais opções de gerenciamento em longo prazo. A solução baseada no Cloud VPN ou no Cloud Interconnect é implementada por uma equipe de rede e inicialmente requer menos integração com o aplicativo legado. No entanto, ela não adiciona qualquer valor agregado em longo prazo.

O processo de migração

Nesta seção você verá as etapas gerais para migrar para a nova arquitetura.

Pré-requisitos

Antes de migrar o primeiro microsserviço para o GKE, você precisa preparar o ambiente do GCP em que trabalhará. Siga as etapas abaixo antes de colocar o primeiro microsserviço em produção no GKE:

  • Configure sua organização do GCP, que é o ambiente global que hospedará seus recursos do GCP. Como parte desta etapa, configure também suas identidades do Google, as contas que os funcionários da sua organização precisam para usar os produtos do Google. Esse processo está descrito em Práticas recomendadas para organizações empresariais.
  • Crie políticas para controlar seus recursos do GCP. Se precisar de ajuda, consulte o artigo Desenvolvimento de políticas para clientes empresariais.
  • Crie um plano para implantar seus recursos do GCP, incluindo clusters do GKE, usando infraestrutura como código (IaC, na sigla em inglês). Assim, você terá ambientes padronizados, reproduzíveis e auditáveis. Para fazer isso, recomendamos o Cloud Deployment Manager ou o Terraform. Todos os recursos para uma IaC no GCP estão disponíveis na página Infraestrutura como código.
  • Estude os diferentes recursos do GKE e ajuste-os conforme necessário. No caso de aplicativos essenciais para o negócio, é recomendável alterar alguns padrões e aumentar a proteção dos clusters. Os documentos Como preparar um ambiente do GKE para produção e Como aumentar a segurança do cluster contêm informações sobre como fazer isso.
  • Crie ferramentas de integração e entrega contínuas (CI/CD) para o Kubernetes. É possível usar o Cloud Build para criar imagens de contêineres e o Container Registry para armazená-las e detectar vulnerabilidades.Também é possível combinar esses produtos com suas ferramentas de CI/CD atuais. Aproveite esse trabalho e implemente as práticas recomendadas para criar e operar contêineres. Fazer isso logo no início do projeto evitará problemas quando você estiver em produção.
  • Dependendo da opção escolhida, configure uma conta da Apigee ou uma conexão privada entre o GCP e seu data center local com o Cloud VPN ou o Cloud Interconnect.

Como migrar em etapas

É necessário migrar os recursos do site de comércio eletrônico um por um para o novo ambiente, criando microsserviços quando necessário. Esses microsserviços podem fazer chamadas para o sistema legado quando necessário.

Essa abordagem é equivalente a transformar a migração completa e refatorar o projeto em vários projetos menores. Proceder dessa maneira tem duas vantagens:

  • Cada projeto menor é mais facilmente delimitado e pensado do que o projeto geral de migração. Fazer a migração do site inteiro em um único esforço exige que as equipes entendam mais sobre as interações entre sistemas, restrições, sistemas de terceiros que dependem do site estar disponível e assim por diante. E isso aumenta o risco de erros.
  • Ter muitos projetos menores dá mais flexibilidade. Se você tiver uma equipe pequena, ela poderá trabalhar nesses projetos, um após o outro, sem ficar sobrecarregada. Se você tiver várias equipes, talvez seja necessário fazer partes do trabalho em paralelo e conduzir várias migrações por vez.

Escolher quais recursos migrar e quando isso será feito é uma das decisões mais importantes a serem tomadas durante esse estágio do projeto. Ao tomar essa decisão, pense na teia de dependências entre os recursos. Alguns recursos podem depender muito de outros para funcionar corretamente, enquanto outros podem ser bastante independentes. Quanto menos dependências um recurso tiver, mais fácil será migrá-lo. A questão das dependências, além de outros fatores a serem pensados ao decidir qual recurso migrar, será abordada com mais detalhes posteriormente na seção Quais recursos migrar primeiro?

Exemplo: como migrar um carrinho de compras

Para ilustrar o processo, esta seção traz uma análise da migração de um único recurso, mais especificamente o carrinho de compras de um site de comércio eletrônico.

Para entender as dependências desse recurso, pense em como normalmente é a jornada do usuário e como ela é implementada em um aplicativo monolítico:

  1. O usuário navega pelo site e encontra o item que ele quer.
  2. O usuário clica em Adicionar ao carrinho de compras. Essa ação aciona uma chamada de API do navegador do usuário para o recurso de carrinho de compras. Essa é a primeira dependência: o front-end atuando no carrinho de compras.
  3. Quando esse recurso recebe a chamada, ele verifica se ainda há esse item no estoque. Esse evento aciona uma chamada de API do recurso de carrinho de compras para o sistema que processa o estoque. Essa é a segunda dependência: o carrinho de compras depende do subsistema do estoque.
  4. Se o estoque tiver esse item, o recurso de carrinho de compras armazenará informações como “o usuário A tem 1 instância do item X no carrinho”. Essa é a terceira dependência: o carrinho de compras precisa de um banco de dados para armazenar essas informações.
  5. Quando o usuário finaliza a compra e passa pelo processo de pagamento, o carrinho de compras é consultado pelo subsistema de pagamento para calcular o valor total. Quando o pagamento é concluído, o subsistema de pagamento notifica o recurso de carrinho de compras para esvaziá-lo. Essa é a quarta dependência: o carrinho de compras é consultado pelo subsistema de pagamento.

Para resumir, o recurso de carrinho de compras é chamado pelo front-end e pelo subsistema de pagamento, e ele consulta um banco de dados e o subsistema de estoque.

Um banco de dados de documentos é ideal para armazenar carrinhos de compras. Você não precisa do poder da capacidade dos bancos de dados relacionais para armazenar dados de carrinho de compras. Além disso, os carrinhos de compras podem ser facilmente indexados por códigos de usuários. O Cloud Firestore é um banco de dados de documentos NoSQL gerenciado e sem servidor que é bastante adequado para esse caso de uso. Portanto, ele é o armazenamento de dados sugerido para a arquitetura final.

É possível migrar os dados do carrinho de compras de várias maneiras. Esse tópico é abordado em mais detalhes posteriormente na seção Estratégias de migração de dados. Neste documento, pressupõe-se que a abordagem de manutenção programada descrita mais adiante é aceitável. Sob essas condições, é possível migrar o recurso de carrinho de compras seguindo estas etapas gerais:

  1. Crie um microsserviço novo que implemente uma API de carrinho de compras. Use o Cloud Firestore para armazenar os carrinhos de compras. Verifique se o microsserviço novo é capaz de chamar o subsistema de estoque.
  2. Crie um script que extraia os carrinhos de compras do subsistema legado e os grave no Cloud Firestore. Escreva o script de forma que seja possível executá-lo novamente quantas vezes forem necessárias. O script precisa copiar apenas os carrinhos de compras que foram alterados desde a última execução.
  3. Crie um script que faça o mesmo, mas de modo inverso: copia os carrinhos de compras do Cloud Firestore para o sistema legado. Use esse script apenas se precisar reverter a migração.
  4. Exponha a API de carrinho de compras com a Apigee.
  5. Prepare e teste as modificações no front-end e no subsistema de pagamento para que eles sejam capazes de chamar o novo microsserviço de carrinho de compras.
  6. Execute o script de migração de dados que você criou na segunda etapa.
  7. Coloque o site em modo de manutenção.
  8. Execute novamente o script de migração de dados.
  9. Implante as modificações da quinta etapa no sistema de produção legado.
  10. Desative o modo de manutenção no site.

O recurso de carrinho de compras do site agora é um microsserviço hospedado no GCP. A quinta etapa provavelmente é a mais difícil do processo porque requer que o sistema legado seja modificado. No entanto, ela fica mais fácil à medida que os demais recursos são migrados para microsserviços porque um número maior de dependências já terá sido transformado em microsserviços. Assim, eles serão acoplados mais levemente do que em um aplicativo monolítico. Portanto, será mais fácil de modificá-los e implantá-los.

Como um processo alternativo de migração, é possível fazer com que o microsserviço novo chame o banco de dados de carrinho de compras original e depois migre os dados para o Cloud Firestore. Para escolher entre esses dois modelos de migração, pense na latência entre o microsserviço e o banco de dados original, a complexidade da refatoração do esquema e a estratégia de migração de dados que você quer adotar.

Quais recursos migrar primeiro?

Nesta seção, você aprenderá a identificar os recursos que precisam ser migrados primeiro: o esforço inicial de migração. Adotar uma abordagem "dividir e conquistar" é sempre o mais indicado para reduzir os riscos inerentes das migrações complexas.

Quando você planeja a migração, é tentador começar com recursos que são fáceis de mover. Isso pode parecer uma vitória rápida, mas talvez não seja a melhor experiência de aprendizado para sua equipe. Em vez de realizar a migração diretamente, dedique um tempo para avaliar todos os recursos e planejar como eles serão movidos.

Se você quiser, use a lista de áreas de avaliação abaixo como um framework da sua análise de cada recurso:

  • Processos de negócios
  • Projeto e desenvolvimento
  • Operações
  • Pessoas e equipes

Avaliação dos processos do negócio

A equipe de migração aprenderá e desenvolverá processos durante os esforços iniciais de migração, e eles provavelmente cometerão erros. Para evitar o impacto na linha principal da empresa, não é recomendável envolver sistemas essenciais ao negócio nessa etapa inicial. No entanto, os recursos envolvidos precisam representar casos de uso significativos. Assim, a equipe terá a oportunidade de aprender. Ao avaliar os processos do negócio, pense também naqueles relacionados à conformidade e ao licenciamento, não apenas nos que se referem ao desenvolvimento.

Avaliação do projeto e desenvolvimento

Do ponto de vista do projeto e do desenvolvimento, as primeiras migrações ideais são aquelas que envolvem o menor número de dependências com outros recursos e dados e que são mais fáceis de refatorar, se necessário.

Analise cada recurso, pensando nas dependências e no esforço necessário para a refatoração. Leve em consideração o seguinte ao analisar as dependências de cada recurso:

  • Tipo da dependência: dependências de dados ou outros recursos.
  • Escala da dependência: quantos recursos serão afetados por uma alteração nas dependências desse recurso.

Migrar um recurso com muitas dependências de dados geralmente não é uma tarefa banal pelos seguintes motivos:

  • Se você decidir migrar os recursos primeiro e os dados relacionados posteriormente, será necessário levar em conta o aumento da latência de rede entre produtores, consumidores e armazenamentos de dados após a primeira migração.
  • Surgirão desafios relacionados a sincronização e integridade de dados durante a fase de migração porque é provável que você temporariamente leia e grave dados em vários locais.

Outra fator a ser avaliado é a quantidade de refatoração necessária para cada recurso. A refatoração em potencial depende tanto do projeto atual quanto da direção futura do recurso. Ao calcular a estimativa, pense em como esse esforço pode afetar os processos de negócios relacionados.

Veja abaixo as perguntas mais importantes que você precisa responder durante essa avaliação:

  • Quais dados esse recurso usa?
  • Quantos dados esse recurso usa?
  • Esse recurso precisa de outros recursos para funcionar corretamente?
  • Quantos outros recursos são afetados por uma alteração nesse recurso?
  • Há algum requisito de rede ou conectividade para esse recurso?
  • Como o projeto atual desse recurso afeta a refatoração?

Avaliação das operações

Do ponto de vista operacional, leve em consideração também quais recursos podem arcar com o tempo de inatividade de uma janela de transferência. Se você precisar minimizar o tempo de inatividade, a migração de recursos que exigem alta disponibilidade pode significar um trabalho extra.

Avaliação de pessoas e equipes

De preferência, escolha equipes que tenham processos bem definidos para conduzir as primeiras migrações. Além disso, as equipes precisam estar dispostas a pavimentar o caminho para a jornada de migração e entender que encontrarão desafios novos que elas precisam solucionar.

Como escolher quais serão as primeiras migrações

De acordo o framework de avaliação acima, o candidato ideal para as primeiras migrações precisa ser desafiador o bastante para que seja significativo, mas simples o suficiente para minimizar os riscos de falha. O processo inicial de migração também precisa:

  • exigir pouca refatoração, levando em consideração tanto o recurso em si quanto os processos de negócios relacionados;
  • ser sem estado, ou seja, não ter requisitos de dados externos;
  • ter nenhuma ou poucas dependências.

Exemplo de plano de migração

A lista a seguir mostra um exemplo de ordem de migração:

  1. Front-end da plataforma, isto é, a interface do usuário;
  2. Recursos sem estado, como um serviço de conversão de moedas;
  3. Funcionalidades com conjuntos de dados independentes (conjuntos de dados sem dependências de outros conjuntos de dados), como um serviço para listar as lojas físicas;
  4. Recursos com conjuntos de dados compartilhados: a lógica de negócios da plataforma de comércio eletrônico.

Front-end da plataforma e recursos sem estado

Os front-ends de plataformas e recursos sem estado normalmente têm poucas dependências. Ambos são candidatos ideais para a migração inicial porque não são componentes banais da arquitetura. Eles exigem refatoração limitada porque na fase inicial de migração a API de back-end ainda é exibida pelo data center legado ou pelo ambiente de execução hospedado por outro provedor de nuvem.

Tanto no caso dos recursos sem estado quanto nos de front-end da plataforma, concentre-se no pipeline de integração e implantação. Como as cargas de trabalho do GKE precisam ser colocadas em contêineres, talvez seja necessário fazer um trabalho operacional maior.

Recursos com conjuntos de dados independentes

Os próximos componentes a serem migrados são recursos com conjuntos de dados independentes de outros conjuntos de dados. Eles são mais fáceis de extrair do sistema legado do que conjuntos de dados que têm dependências. É claro que em comparação à migração de recursos sem estado, migrar recursos com conjuntos de dados independentes exige mais trabalho, a saber, criar e gerenciar o novo armazenamento de dados juntamente com a própria migração dos dados.

Ao planejar a migração de dados, você tem opções de sistemas de armazenamento a seu dispor. Mas como você quer modernizar seus aplicativos, use o seguinte:

  • Serviços gerenciados de armazenamento de dados, como o Cloud Storage ou o Cloud Filestore, para armazenar arquivos
  • Cloud SQL para migrar dados de um RDBMS
  • Cloud Firestore para migrar dados de um banco de dados NoSQL

Recursos com conjuntos de dados compartilhados

Os recursos com conjuntos de dados compartilhados são os mais difíceis de migrar. Como detalhado posteriormente, isso se dá ao fato de que a migração de dados é uma tarefa desafiadora por causa dos requisitos de consistência, distribuição, acesso e latência.

Estratégias de migração de dados

Ao migrar dados, siga esta abordagem geral:

  1. Transferira dados do site legado para o novo.
  2. Solucione todos os problemas de integração de dados que surgirem, por exemplo, sincronizando os mesmos dados de várias fontes.
  3. Valide a migração de dados.
  4. Promova o novo site para que seja a cópia mestre.
  5. Desative o site legado quando não precisar mais dele como uma opção substituta.

Baseie sua estratégia de migração de dados nas perguntas a seguir:

  • Qual a quantidade de dados você precisa migrar?
  • Com que frequência esses dados mudam?
  • Você pode arcar com o tempo de inatividade representado por uma janela de transferência durante a migração dos dados?
  • Qual é seu modelo atual de consistência de dados?

Não há uma abordagem perfeita. Essa escolha depende do ambiente e de seus requisitos.

As seções a seguir apresentam quatro abordagens de migração de dados:

  • Manutenção programada
  • Replicação contínua
  • Y (gravação e leitura)
  • Microsserviço de acesso a dados

Cada abordagem soluciona problemas diferentes, dependendo da escala e dos requisitos da migração de dados.

A abordagem de microsserviço de acesso a dados é a opção preferida para uma arquitetura de microsserviços. No entanto, as outras abordagens são úteis para a migração de dados. Elas também são úteis durante o período de transição necessário para modernizar a infraestrutura o suficiente para adotar a abordagem de microsserviço de acesso a dados.

O gráfico a seguir ilustra respectivamente os tamanhos das janelas de transferência, os esforços de refatoração e as propriedades de flexibilidade de cada uma das abordagens.

Gráfico de barras que mostra os valores relativos de flexibilidade, esforço de refatoração e tamanhos de janela de transferência de cada uma das quatro abordagens

Antes de adotar qualquer uma dessas abordagens, verifique se você configurou a infraestrutura necessária no novo ambiente.

Manutenção programada

A abordagem de manutenção programada é ideal se as cargas de trabalho podem arcar com a janela de transferência. Programação neste contexto significa que é possível planejar quando a janela de transferência ocorre.

Nesta abordagem, a migração consiste nas seguintes etapas:

  1. Copie os dados que atualmente estão no site legado para o novo. Essa cópia inicial minimiza a janela de transferência. Depois dela, será necessário copiar apenas os dados que foram alterados durante a janela.
  2. Execute verificações de validação e consistência de dados para comparar os dados copiados no novo site com aqueles que estão no site legado.
  3. Interrompa as cargas de trabalho e os serviços com acesso de gravação aos dados copiados para que não ocorram mais alterações.
  4. Sincronize as alterações ocorridas após a cópia inicial.
  5. Refatore as cargas de trabalho e os serviços para usar o site novo.
  6. Inicie as cargas de trabalho e os serviços.
  7. Desative o site legado quando não precisar mais dele como uma opção substituta.

A abordagem de manutenção programada coloca um fardo maior sobre a equipe de operações porque é necessário realizar um mínimo de refatoração de cargas de trabalho e serviços.

Replicação contínua

Como nem todas as cargas de trabalho podem arcar com uma janela de transferência longa, é possível desenvolver uma abordagem com base na manutenção programada, disponibilizando um mecanismo de replicação contínua após as etapas de cópia inicial e validação. Ao projetar um mecanismo desse tipo, você também precisa levar em consideração a taxa de aplicação de alterações aos dados. Talvez seja desafiador manter dois sistemas sincronizados.

A abordagem de replicação contínua é mais complexa do que a manutenção programada. No entanto, ela minimiza o tempo da janela de transferência necessária porque reduz a quantidade de dados que precisam ser sincronizados. A sequência da migração na abordagem de replicação contínua é a seguinte:

  1. Copie os dados que atualmente estão no site legado para o novo. Essa cópia inicial minimiza a janela de transferência. Depois dela, será necessário copiar apenas os dados que foram alterados durante a janela.
  2. Execute verificações de validação e consistência de dados para comparar os dados copiados no novo site com aqueles que estão no site legado.
  3. Configure um mecanismo de replicação contínua do site legado para o novo.
  4. Interrompa as cargas de trabalho e os serviços com acesso aos dados a serem migrados, isto é, aos dados envolvidos na etapa anterior.
  5. Reestruture as cargas de trabalho e os serviços para usar o site novo.
  6. Aguarde a replicação para sincronizar totalmente o novo site com o legado.
  7. Inicie as cargas de trabalho e os serviços.
  8. Desative o site legado quando não precisar mais dele como uma opção substituta.

Assim como na abordagem de manutenção programada, a abordagem de replicação contínua coloca um fardo maior sobre a equipe de operações.

Y (gravação e leitura)

Se as cargas de trabalho tiverem requisitos rígidos de alta disponibilidade e não for possível arcar com o tempo de inatividade representado pela janela de transferência, adote uma abordagem diferente. Nesse cenário, é possível usar uma abordagem que, neste documento, é mencionada como Y (gravação e leitura), uma forma de migração paralela. Com essa abordagem, a carga de trabalho grava e lê dados tanto no site legado quanto no novo durante a migração. A letra Y é usada aqui como uma representação gráfica do fluxo de dados durante o período de migração.

Essa abordagem é resumida da seguinte maneira:

  1. Refatore as cargas de trabalho e os serviços para ler dados no site legado e gravá-los tanto no legado quanto no novo.
  2. Identifique os dados gravados antes da ativação das gravações no site novo e copie-os do site legado para o novo. Juntamente com a refatoração acima, isso garante que os armazenamentos de dados estejam alinhados.
  3. Execute verificações de validação e consistência de dados para comparar os dados no site legado com aqueles no novo.
  4. Alterne as operações de leitura do site legado para o novo.
  5. Realize outra rodada de verificações de validação e consistência de dados para comparar os dados no site legado com aqueles no novo.
  6. Desative a gravação no site legado.
  7. Desative o site legado quando não precisar mais dele como uma opção substituta.

Ao contrário da manutenção programada e da replicação contínua, a abordagem em Y (gravação e leitura) tira a maior parte da sobrecarga da equipe de operações e a coloca sobre a equipe de desenvolvimento, devido às várias refatorações.

Microsserviço de acesso a dados

Se você quiser reduzir o esforço de refatoração necessário para seguir a abordagem em Y (gravação e leitura), centralize as operações de leitura e gravação de dados refatorando cargas de trabalho e serviços para usar um microsserviço de acesso a dados. Esse microsserviço escalonável será o único ponto de entrada para a camada de armazenamento de dados e atuará como um proxy dessa camada. Dentre as abordagens discutidas aqui, é esta que oferece a máxima flexibilidade porque é possível refatorar esse componente da arquitetura sem afetar os demais nem precisar de uma janela de transferência.

Usar um microsserviço de acesso a dados é muito parecido com a abordagem em Y (gravação e leitura). A diferença é que os esforços de refatoração se concentram apenas no microsserviço de acesso a dados, em vez de na necessidade de refatorar todas as cargas de trabalho e os serviços que acessam a camada de armazenamento de dados. Essa abordagem é resumida da seguinte maneira:

  1. Refatore o microsserviço de acesso a dados para gravar dados tanto no site legado quanto no novo. As leituras são realizadas no site legado.
  2. Identifique os dados gravados antes da ativação das gravações no site novo e copie-os do site legado para o novo. Juntamente com a refatoração acima, isso garante que os armazenamentos de dados estejam alinhados.
  3. Execute verificações de validação e consistência de dados para comparar os dados no site legado com aqueles no novo.
  4. Refatore o microsserviço de acesso a dados para fazer leituras no site novo.
  5. Realize outra rodada de verificações de validação e consistência de dados para comparar os dados no site legado com aqueles no novo.
  6. Refatore o microsserviço de acesso a dados para realizar gravações apenas no site legado.
  7. Desative o site legado quando não precisar mais dele como uma opção substituta.

Assim como a abordagem em Y (gravação e leitura), a abordagem de microsserviço de acesso a dados coloca um fardo maior sobre a equipe de desenvolvimento. No entanto, é um trabalho significativamente mais leve se comparado com a abordagem anterior porque os esforços de refatoração são concentrados no microsserviço de acesso a dados.

Práticas recomendadas para microsserviços

As seções a seguir incluem um conjunto de práticas recomendadas a serem seguidas na hora de projetar, escrever e implantar microsserviços.

Como projetar microsserviços

Ao projetar seus microsserviços, siga um padrão de projeto que permita determinar corretamente o contexto e o limite de cada um deles. Dessa forma, haverá uma proteção contra a fragmentação desnecessária das cargas de trabalho dos seus microsserviços. Além disso, será possível definir um contexto (ou domínio) preciso em que os microsserviços serão válidos. Um exemplo desse padrão de projeto é o projeto orientado por domínio (DDD, na sigla em inglês).

Contratos de API

É necessário que cada microsserviço seja invocado a partir de apenas um conjunto de interfaces. Por sua vez, é necessário que cada interface seja claramente definida por um contrato que pode ser implementado usando uma linguagem de definição de API, como a especificação da OpenAPI Initiative (anteriormente Swagger) ou RAML. Ter interfaces e contratos de API bem definidos permite desenvolver testes como um componente principal da sua solução (por exemplo, por meio da aplicação do desenvolvimento orientado por testes) nessas interfaces.

Como gerenciar as alterações

Caso seja necessário introduzir alterações interruptivas nos contratos de API, prepare-se com antecedência para minimizar o esforço de refatoração que será necessário para que os clientes deem conta das alterações. Duas maneiras de lidar com esse problema são:

  • controle de versão;
  • implementação de um microsserviço novo.

Controle de versão

Para aumentar a flexibilidade do gerenciamento de atualizações que podem interromper os clientes atuais, implemente um esquema de controle de versão para os microsserviços. Com o controle de versão, é possível implantar versões atualizadas de um microsserviço sem afetar os clientes que estão usando uma versão atual. Se você usar o controle de versão, precisará criar uma versão nova sempre que introduzir uma alteração que interrompe qualquer parte de um contrato atual, mesmo que essa alteração seja mínima.

É possível implementar o controle de versão usando os esquemas a seguir:

  • Controle de versão global
  • Controle de versão de recurso

Ao implementar um esquema de controle de versão global, está implícito que o controle de versão é feito para a API inteira. Uma implementação é criar as informações da versão nos URIs dos recursos, como abaixo:

/api/v1/entities or api.v3.domain.tld/entities

Esse tipo de esquema é fácil de implantar porque o controle de versão é gerenciado em um único lugar. No entanto, ele não é tão flexível quanto o esquema de controle de versão de recurso. Para ver um exemplo de esquema de controle de versão global, consulte o esquema de controle de versão da API do Kubernetes (em inglês).

Com um esquema de controle de versão de recurso, é possível editar de modo independente cada recurso exibido pelo microsserviço. Para ter o máximo de flexibilidade, é possível até mesmo fazer o controle de versão de um determinado recurso de acordo com a operação nele, por exemplo, o verbo HTTP. É possível implementar esse esquema de controle de versão de várias maneiras. Use URIs ou cabeçalhos de solicitação HTTP personalizados ou padrão, como no exemplo a seguir:

Accept: application/tld.domain.entities.v2+json

Talvez seja mais difícil projetar um esquema de controle de versão de recurso do que de versão global porque é necessário adotar uma abordagem generalizada para todas as entidades. No entanto, esse esquema também é mais flexível porque possibilita implementar políticas de upgrade diferentes e independentes para os recursos.

Implementação de um microsserviço novo

Outra abordagem para lidar com as alterações interruptivas é implementar um microsserviço totalmente novo com um contrato inédito. É aconselhável fazer isso quando a versão nova do microsserviço exigir tantas alterações que escrever uma versão diferente é melhor do que corrigir a atual. Ainda que essa abordagem ofereça o máximo de flexibilidade, ela tem o potencial de apresentar microsserviços com funcionalidades e contratos sobrepostos. Depois de implementar o microsserviço novo, será possível refatorar gradualmente os clientes para usá-los e migrar do antigo.

Próximas etapas