Desafios e soluções do gerenciamento de dados distribuídosChallenges and solutions for distributed data management

Desafio #1: Como definir os limites de cada microsserviçoChallenge #1: How to define the boundaries of each microservice

Definir os limites dos microsserviços provavelmente é o primeiro desafio que qualquer pessoa encontra.Defining microservice boundaries is probably the first challenge anyone encounters. Cada microsserviço deve ser uma parte do aplicativo e cada microsserviço deve ser autônomo com todos os benefícios e desafios que ele abrange.Each microservice has to be a piece of your application and each microservice should be autonomous with all the benefits and challenges that it conveys. Mas como identificar esses limites?But how do you identify those boundaries?

Primeiro, você precisa se concentrar nos modelos de domínio lógicos do aplicativo e nos dados relacionados.First, you need to focus on the application's logical domain models and related data. Tente identificar ilhas de dados desacopladas e contextos diferentes dentro do mesmo aplicativo.Try to identify decoupled islands of data and different contexts within the same application. Cada contexto pode ter uma linguagem de negócios diferente (termos de negócios diferentes).Each context could have a different business language (different business terms). Os contextos devem ser definidos e gerenciados de forma independente.The contexts should be defined and managed independently. Os termos e as entidades usados nesses contextos diferentes podem parecer semelhantes, mas você descobrirá que, em um contexto específico, um conceito empresarial é usado para uma finalidade e em outro contexto para outra finalidade, podendo até mesmo ter um nome diferente.The terms and entities that are used in those different contexts might sound similar, but you might discover that in a particular context, a business concept with one is used for a different purpose in another context, and might even have a different name. Por exemplo, um usuário pode ser mencionado como um usuário no contexto de identidade ou de associação, como um cliente em um contexto de CRM, como um comprador em um contexto de pedidos e assim por diante.For instance, a user can be referred as a user in the identity or membership context, as a customer in a CRM context, as a buyer in an ordering context, and so forth.

Sua forma de identificar os limites entre vários contextos de aplicativo com um domínio diferente para cada contexto é exatamente a forma que você pode usar para identificar os limites de cada microsserviço de negócios, além de seu modelo de domínio e seus dados relacionados.The way you identify boundaries between multiple application contexts with a different domain for each context is exactly how you can identify the boundaries for each business microservice and its related domain model and data. Você sempre deve tentar minimizar o acoplamento entre esses microsserviços.You always attempt to minimize the coupling between those microservices. Mais adiante, este guia apresentará mais detalhes sobre essa identificação e esse design de modelo de domínio na seção Identificando limites de modelo de domínio para cada microsserviço.This guide goes into more detail about this identification and domain model design in the section Identifying domain-model boundaries for each microservice later.

Desafio #2: Como criar consultas que recuperam dados de vários microsserviçosChallenge #2: How to create queries that retrieve data from several microservices

Um segundo desafio é como implementar consultas que recuperam dados de vários microsserviços, evitando a comunicação intensa dos aplicativos clientes remotos com os microsserviços.A second challenge is how to implement queries that retrieve data from several microservices, while avoiding chatty communication to the microservices from remote client apps. Um exemplo pode ser uma única tela de um aplicativo móvel que precisa mostrar microsserviços de informações do usuário que pertencem ao carrinho de compras, de catálogo e de identidade do usuário.An example could be a single screen from a mobile app that needs to show user information that's owned by the basket, catalog, and user identity microservices. Outro exemplo seria um relatório complexo envolvendo diversas tabelas localizadas em vários microsserviços.Another example would be a complex report involving many tables located in multiple microservices. A solução certa depende da complexidade das consultas.The right solution depends on the complexity of the queries. Mas em qualquer caso, será necessária uma maneira de agregar informações se você desejar melhorar a eficiência nas comunicações do sistema.But in any case, you'll need a way to aggregate information if you want to improve the efficiency in the communications of your system. As soluções mais comuns são as seguintes.The most popular solutions are the following.

Gateway de API.API Gateway. Para a agregação de dados simples de vários microsserviços que têm bancos de dados diferentes, a abordagem recomendada é um microsserviço de agregação, conhecido como Gateway de API.For simple data aggregation from multiple microservices that own different databases, the recommended approach is an aggregation microservice referred to as an API Gateway. No entanto, você precisa ter cuidado ao implementar esse padrão, porque ele pode ser um ponto de redução no sistema e pode violar o princípio de autonomia dos microsserviços.However, you need to be careful about implementing this pattern, because it can be a choke point in your system, and it can violate the principle of microservice autonomy. Para atenuar essas possibilidades, você pode ter vários Gateways de API refinados, cada um concentrado em uma "fatia" vertical ou em uma área de negócios do sistema.To mitigate this possibility, you can have multiple fined-grained API Gateways each one focusing on a vertical "slice" or business area of the system. O padrão do Gateway de API será explicado mais detalhadamente na seção Gateway de API mais adiante.The API Gateway pattern is explained in more detail in the API Gateway section later.

CQRS com tabelas de consulta/leituras.CQRS with query/reads tables. Outra solução para agregar dados de vários microsserviços é o Padrão de exibição materializada.Another solution for aggregating data from multiple microservices is the Materialized View pattern. Nessa abordagem, você gera com antecedência (prepara os dados desnormalizados antes que as consultas reais ocorram) uma tabela somente leitura com os dados que pertencem a vários microsserviços.In this approach, you generate, in advance (prepare denormalized data before the actual queries happen), a read-only table with the data that's owned by multiple microservices. A tabela tem um formato adequado às necessidades do aplicativo cliente.The table has a format suited to the client app's needs.

Considere algo como tela de um aplicativo móvel.Consider something like the screen for a mobile app. Se houver um banco de dados individual, você poderá reunir os dados para essa tela usando uma consulta SQL que execute uma junção complexa envolvendo várias tabelas.If you have a single database, you might pull together the data for that screen using a SQL query that performs a complex join involving multiple tables. No entanto, quando houver vários bancos de dados, e cada banco de dados pertencer a um microsserviço diferente, você não poderá consultar esses bancos de dados e criar uma junção SQL.However, when you have multiple databases, and each database is owned by a different microservice, you cannot query those databases and create a SQL join. Sua consulta complexa se tornará um desafio.Your complex query becomes a challenge. Você pode atender ao requisito usando uma abordagem de CQRS, ou seja, criar uma tabela desnormalizada em outro banco de dados que é usado apenas para consultas.You can address the requirement using a CQRS approach—you create a denormalized table in a different database that's used just for queries. A tabela pode ser desenvolvida especificamente para os dados necessários para essa consulta complexa, com uma relação um-para-um entre os campos necessários para a tela do aplicativo e as colunas na tabela de consulta.The table can be designed specifically for the data you need for the complex query, with a one-to-one relationship between fields needed by your application's screen and the columns in the query table. Ela também pode funcionar para a geração de relatórios.It could also serve for reporting purposes.

Além de resolver o problema original (como fazer a consulta e a junção entre os microsserviços), essa abordagem também melhora o desempenho consideravelmente em comparação com uma junção complexa, porque os dados que o aplicativo precisa já estão na tabela de consulta.This approach not only solves the original problem (how to query and join across microservices), but it also improves performance considerably when compared with a complex join, because you already have the data that the application needs in the query table. É claro que, o uso de CQRS (segregação de responsabilidade de comando e consulta) com tabelas de consulta/leituras significa um trabalho de desenvolvimento adicional e a necessidade de abranger uma coerência eventual.Of course, using Command and Query Responsibility Segregation (CQRS) with query/reads tables means additional development work, and you'll need to embrace eventual consistency. No entanto, o CQRS com vários bancos de dados deve ser aplicado para atender requisitos de desempenho e de alta escalabilidade em cenários de colaboração (ou cenários de concorrência, dependendo do ponto de vista).Nonetheless, requirements on performance and high scalability in collaborative scenarios (or competitive scenarios, depending on the point of view) are where you should apply CQRS with multiple databases.

"Dados frios" em bancos de dados centrais."Cold data" in central databases. Para relatórios e consultas complexos que talvez não exijam dados em tempo real, uma abordagem comum é exportar os "dados quentes" (dados transacionais dos microsserviços) como "dados frios" para bancos de dados grandes usados somente para relatórios.For complex reports and queries that might not require real-time data, a common approach is to export your "hot data" (transactional data from the microservices) as "cold data" into large databases that are used only for reporting. Esse sistema de banco de dados central pode ser um sistema baseado em Big Data, como o Hadoop, um data warehouse como um baseado no SQL Data Warehouse do Azure ou até mesmo um Banco de Dados SQL individual usado apenas para relatórios (se o tamanho não for problema).That central database system can be a Big Data-based system, like Hadoop, a data warehouse like one based on Azure SQL Data Warehouse, or even a single SQL database that's used just for reports (if size won't be an issue).

Tenha em mente que esse banco de dados centralizado deve ser usado somente para consultas e relatórios que não precisam de dados em tempo real.Keep in mind that this centralized database would be used only for queries and reports that do not need real-time data. As atualizações e transações originais, ou seja, a fonte confiável, precisam estar nos dados dos microsserviços.The original updates and transactions, as your source of truth, have to be in your microservices data. A maneira de sincronizar os dados seria usar a comunicação controlada por evento (abordada nas próximas seções) ou usar outras ferramentas de importação/exportação da infraestrutura do banco de dados.The way you would synchronize data would be either by using event-driven communication (covered in the next sections) or by using other database infrastructure import/export tools. Se você usar a comunicação controlada por evento, esse processo de integração será semelhante à maneira de propagar dados já descrita para tabelas de consulta de CQRS.If you use event-driven communication, that integration process would be similar to the way you propagate data as described earlier for CQRS query tables.

No entanto, se o design do aplicativo envolver a agregação constante de informações de vários microsserviços para consultas complexas, esse poderá ser um sintoma de design ruim, pois um microsserviço deve estar o mais isolado possível dos outros microsserviços.However, if your application design involves constantly aggregating information from multiple microservices for complex queries, it might be a symptom of a bad design -a microservice should be as isolated as possible from other microservices. (Isso exclui relatórios/análises que sempre devem usar bancos de dados do Cold Data Central.) Ter esse problema muitas vezes pode ser um motivo para mesclar os microserviços.(This excludes reports/analytics that always should use cold-data central databases.) Having this problem often might be a reason to merge microservices. Você precisa equilibrar a autonomia de evolução e a implantação de cada microsserviço com dependências fortes, coesão e agregação de dados.You need to balance the autonomy of evolution and deployment of each microservice with strong dependencies, cohesion, and data aggregation.

Desafio #3: Como obter consistência entre vários microsserviçosChallenge #3: How to achieve consistency across multiple microservices

Como mencionado anteriormente, os dados pertencentes a cada microsserviço são privados desse microsserviço e só podem ser acessados usando a API desse microsserviço.As stated previously, the data owned by each microservice is private to that microservice and can only be accessed using its microservice API. Portanto, um desafio apresentado é como implementar processos de negócios de ponta a ponta, mantendo a consistência entre vários microsserviços.Therefore, a challenge presented is how to implement end-to-end business processes while keeping consistency across multiple microservices.

Para analisar o problema, vamos examinar um exemplo do Aplicativo de referência eShopOnContainers.To analyze this problem, let's look at an example from the eShopOnContainers reference application. O microsserviço de catálogo mantém informações sobre todos os produtos, incluindo o preço do produto.The Catalog microservice maintains information about all the products, including the product price. O microsserviço Carrinho de compras gerencia dados temporais sobre itens de produto que os usuários estão adicionando aos seus carrinhos de compras, o que inclui o preço dos itens no momento em que eles foram adicionados ao carrinho de compras.The Basket microservice manages temporal data about product items that users are adding to their shopping baskets, which includes the price of the items at the time they were added to the basket. Quando o preço de um produto é atualizado no catálogo, esse preço também deve ser atualizado nos carrinhos de compras ativos que contêm o mesmo produto e, além disso, o sistema provavelmente deve avisar o usuário, informando que o preço de um determinado item foi alterado desde que o usuário o adicionou ao seu carrinho de compras.When a product's price is updated in the catalog, that price should also be updated in the active baskets that hold that same product, plus the system should probably warn the user saying that a particular item's price has changed since they added it to their basket.

Em uma versão monolítica hipotética deste aplicativo, quando o preço é alterado na tabela de produtos, o subsistema de catálogo pode simplesmente usar uma transação ACID para atualizar o preço atual na tabela de Carrinho de compras.In a hypothetical monolithic version of this application, when the price changes in the products table, the catalog subsystem could simply use an ACID transaction to update the current price in the Basket table.

No entanto, em um aplicativo baseado em microsserviços, as tabelas de Produto e Carrinho de compras pertencem aos seus respectivos microsserviços.However, in a microservices-based application, the Product and Basket tables are owned by their respective microservices. Um microsserviço nunca deve incluir tabelas/armazenamento pertencentes a outro microsserviço em suas próprias transações, nem mesmo em consultas diretas, conforme é mostrado na Figura 4-9.No microservice should ever include tables/storage owned by another microservice in its own transactions, not even in direct queries, as shown in Figure 4-9.

Diagrama mostrando que não é possível compartilhar os dados do banco de dado dos microservices.

Figura 4-9.Figure 4-9. Um microsserviço não pode acessar diretamente uma tabela em outro microsserviçoA microservice can't directly access a table in another microservice

O microsserviço de Catálogo não deve atualizar a tabela de Carrinho de compras diretamente, porque a tabela de Carrinho de compras é de propriedade do microsserviço de Carrinho de compras.The Catalog microservice shouldn't update the Basket table directly, because the Basket table is owned by the Basket microservice. Para fazer uma atualização no microsserviço de Carrinho de compras, o microsserviço de Catálogo deve usar a consistência eventual provavelmente com base comunicação assíncrona, assim como em eventos de integração (comunicação baseada em mensagem e em evento).To make an update to the Basket microservice, the Catalog microservice should use eventual consistency probably based on asynchronous communication such as integration events (message and event-based communication). É assim que o aplicativo de referência eShopOnContainers executa esse tipo de consistência entre microsserviços.This is how the eShopOnContainers reference application performs this type of consistency across microservices.

Conforme indicado pelo Teorema CAP, é necessário escolher entre a disponibilidade e a coerência forte de ACID.As stated by the CAP theorem, you need to choose between availability and ACID strong consistency. A maioria dos cenários baseados em microsserviço exigem disponibilidade e alta escalabilidade em vez de coerência forte.Most microservice-based scenarios demand availability and high scalability as opposed to strong consistency. Os aplicativos críticos precisam permanecer em funcionamento e os desenvolvedores podem contornar a coerência forte usando técnicas para trabalhar com consistência eventual ou fraca.Mission-critical applications must remain up and running, and developers can work around strong consistency by using techniques for working with weak or eventual consistency. Essa é a abordagem usada pela maioria das arquiteturas baseadas em microsserviço.This is the approach taken by most microservice-based architectures.

Além de o estilo ACID ou as transações de confirmação de duas fases serem contra os princípios dos microsserviços, a maioria dos bancos de dados NoSQL (como o Azure Cosmos DB, o MongoDB, etc.) não dão suporte às transações de confirmação de duas fases, típicas em cenários de bancos de dados distribuídos.Moreover, ACID-style or two-phase commit transactions are not just against microservices principles; most NoSQL databases (like Azure Cosmos DB, MongoDB, etc.) do not support two-phase commit transactions, typical in distributed databases scenarios. No entanto, manter a consistência dos dados entre os serviços e os bancos de dados é fundamental.However, maintaining data consistency across services and databases is essential. Esse desafio também está relacionado à questão de como propagar alterações entre vários microsserviços quando determinados dados precisam ser redundante. Por exemplo, quando o nome ou a descrição do produto precisa estar no microsserviço de catálogo e também no microsserviço de Carrinho de compras.This challenge is also related to the question of how to propagate changes across multiple microservices when certain data needs to be redundant—for example, when you need to have the product's name or description in the Catalog microservice and the Basket microservice.

Uma boa solução para esse problema é usar a consistência eventual entre os microsserviços, articulada pela comunicação controlada por evento e por um sistema de publicação e assinatura.A good solution for this problem is to use eventual consistency between microservices articulated through event-driven communication and a publish-and-subscribe system. Esses tópicos serão abordados na seção Comunicação controlada por evento assíncrono mais adiante neste guia.These topics are covered in the section Asynchronous event-driven communication later in this guide.

Desafio #4: Como projetar a comunicação entre os limites dos microsserviçosChallenge #4: How to design communication across microservice boundaries

A comunicação entre os limites dos microsserviços é realmente um grande desafio.Communicating across microservice boundaries is a real challenge. Nesse contexto, a comunicação não se refere a qual protocolo você deve usar (HTTP e REST, AMQP, mensagens e assim por diante).In this context, communication doesn't refer to what protocol you should use (HTTP and REST, AMQP, messaging, and so on). Nesse caso, ela aborda qual estilo de comunicação você deve usar e, principalmente, que nível de acoplamento os microsserviços devem ter.Instead, it addresses what communication style you should use, and especially how coupled your microservices should be. Dependendo do nível de acoplamento, quando ocorrer uma falha, o impacto dessa falha no sistema poderá variar significativamente.Depending on the level of coupling, when failure occurs, the impact of that failure on your system will vary significantly.

Em um sistema distribuído, como um aplicativo baseado em microsserviços, com um número muito grande de artefatos em movimentação, com serviços distribuídos em vários servidores ou hosts, eventualmente, os componentes falharão.In a distributed system like a microservices-based application, with so many artifacts moving around and with distributed services across many servers or hosts, components will eventually fail. Falhas parciais e interrupções ainda maiores certamente ocorrerão, portanto, você precisa projetar seus microsserviços e a comunicação entre eles levando em conta os riscos comuns nesse tipo de sistema distribuído.Partial failure and even larger outages will occur, so you need to design your microservices and the communication across them considering the common risks in this type of distributed system.

Uma abordagem comum é implementar microsserviços baseados em HTTP (REST), devido à simplicidade.A popular approach is to implement HTTP (REST)-based microservices, due to their simplicity. Uma abordagem baseada em HTTP é perfeitamente aceitável e, nesse caso, o problema está relacionado à maneira de usá-la.An HTTP-based approach is perfectly acceptable; the issue here is related to how you use it. Se você usar solicitações e respostas HTTP apenas para que os aplicativos cliente ou os gateways de API interajam com os microsserviços, tudo bem.If you use HTTP requests and responses just to interact with your microservices from client applications or from API Gateways, that's fine. Mas, se você criar longas cadeias de chamadas HTTP síncronas entre os microsserviços, comunicando-se entre seus limites como se os microsserviços fossem objetos em um aplicativo monolítico, seu aplicativo acabará tendo problemas.But if you create long chains of synchronous HTTP calls across microservices, communicating across their boundaries as if the microservices were objects in a monolithic application, your application will eventually run into problems.

Por exemplo, imagine que o aplicativo cliente faça uma chamada HTTP à API para um microsserviço individual, como o microsserviço de pedidos.For instance, imagine that your client application makes an HTTP API call to an individual microservice like the Ordering microservice. Se o microsserviço de pedidos, por sua vez, chamar microsserviços adicionais usando HTTP no mesmo ciclo de solicitação/resposta, você estará criando uma cadeia de chamadas HTTP.If the Ordering microservice in turn calls additional microservices using HTTP within the same request/response cycle, you're creating a chain of HTTP calls. Parece razoável em um primeiro momento.It might sound reasonable initially. No entanto, existem pontos importantes a serem considerados ao adotar esse caminho:However, there are important points to consider when going down this path:

  • Bloqueio e baixo desempenho.Blocking and low performance. Devido à natureza síncrona de HTTP, a solicitação original não obtém uma resposta até que todas as chamadas HTTP internas sejam concluídas.Due to the synchronous nature of HTTP, the original request doesn't get a response until all the internal HTTP calls are finished. Imagine se o número dessas chamadas aumentar significativamente e ao mesmo tempo uma das chamadas HTTP intermediárias para um microsserviço for bloqueada.Imagine if the number of these calls increases significantly and at the same time one of the intermediate HTTP calls to a microservice is blocked. O resultado é que o desempenho será afetado e a escalabilidade geral será extremamente afetada com o aumento de solicitações HTTP adicionais.The result is that performance is impacted, and the overall scalability will be exponentially affected as additional HTTP requests increase.

  • Acoplando microsserviços com HTTP.Coupling microservices with HTTP. Os microsserviços empresariais não devem ser acoplados com outros microsserviços empresariais.Business microservices shouldn't be coupled with other business microservices. O ideal é que eles não "saibam" da existência de outros microsserviços.Ideally, they shouldn't "know" about the existence of other microservices. Se seu aplicativo depender do acoplamento de microsserviços como no exemplo, será praticamente impossível alcançar a autonomia de cada microsserviço.If your application relies on coupling microservices as in the example, achieving autonomy per microservice will be almost impossible.

  • Falha em um dos microsserviços.Failure in any one microservice. Se você implementar uma cadeia de microsserviços vinculados por chamadas HTTP, quando um dos microsserviços falhar (e, com certeza, isso vai ocorrer) toda a cadeia de microsserviços falhará.If you implemented a chain of microservices linked by HTTP calls, when any of the microservices fails (and eventually they will fail) the whole chain of microservices will fail. Um sistema baseado em microsserviço deve ser criado para continuar a trabalhar da melhor maneira possível durante falhas parciais.A microservice-based system should be designed to continue to work as well as possible during partial failures. Mesmo se você implementar uma lógica do cliente que use novas tentativas com retirada exponencial ou com mecanismos de disjuntor, quanto mais complexas as cadeias de chamadas HTTP forem, mais complexa será a implementação de uma estratégia de falha baseada em HTTP.Even if you implement client logic that uses retries with exponential backoff or circuit breaker mechanisms, the more complex the HTTP call chains are, the more complex it is to implement a failure strategy based on HTTP.

Na verdade, se os microsserviços internos estiverem se comunicando por meio da criação de cadeias de solicitações HTTP, conforme descrito, será possível argumentar que você tem um aplicativo monolítico, mas baseado em HTTP entre processos e não em mecanismos de comunicação entre processos.In fact, if your internal microservices are communicating by creating chains of HTTP requests as described, it could be argued that you have a monolithic application, but one based on HTTP between processes instead of intra-process communication mechanisms.

Portanto, para impor a autonomia do microsserviço e melhorar a resiliência, você deve minimizar o uso de cadeias de comunicação de solicitação/resposta entre os microsserviços.Therefore, in order to enforce microservice autonomy and have better resiliency, you should minimize the use of chains of request/response communication across microservices. É recomendável usar somente a interação assíncrona para a comunicação entre os microsserviços, seja usando a comunicação assíncrona baseada em evento e em mensagem ou usando a sondagem de HTTP (assíncrona), independentemente do ciclo de solicitação/resposta HTTP original.It's recommended that you use only asynchronous interaction for inter-microservice communication, either by using asynchronous message- and event-based communication, or by using (asynchronous) HTTP polling independently of the original HTTP request/response cycle.

O uso da comunicação assíncrona será explicado em detalhes mais adiante neste guia nas seções A integração assíncrona dos microsserviços impõe a autonomia do microsserviço e Comunicação assíncrona baseada em mensagem.The use of asynchronous communication is explained with additional details later in this guide in the sections Asynchronous microservice integration enforces microservice's autonomy and Asynchronous message-based communication.

Recursos adicionaisAdditional resources