Principais formas de comunicação entre microsserviços

Sobre mim

Vinícius Campitelli

Vinícius Campitelli

  • Membro do PHPSP
  • Desenvolvedor na OTTera
  • Entusiasta em cibersegurança
  • Desenvolvedor há mais de 10 anos

Sobre mim

SOA (Service Oriented Architeture)

É um padrão de projeto de software, ou padrão de arquitetura de software de baixo acoplamento, onde as funcionalidades implementadas nas aplicações devem ser disponibilizadas na forma de serviços, acessíveis normalmente via web services, é baseada nos princípios da computação distribuída, que utiliza o paradigma request/reply para estabelecer a comunicação entre os sistemas clientes e os sistemas dos serviços.
Wikipedia

SOA (Service Oriented Architeture)

Exemplo de Arquitetura

Exemplo de arquitetura de SOA
O'Reilly

Microsserviços

A variant of the SOA structural style – arranges an application as a collection of loosely-coupled services. In a microservices architecture, services are fine-grained and the protocols are lightweight.
Wikipedia

Microsserviços

Exemplo de Arquitetura

Exemplo de arquitetura de microsserviços
embarcados.com.br

Principais formas de comunicação

  • HTTP: Geralmente síncrono
    Exemplos: REST, GraphQL
  • IPC: Geralmente Síncrono
    Exemplos: gRPC
  • Mensageria: Assíncrono
    Exemplos: RabbitMQ, Kafka

HTTP

O HTTP (Hypertext Transfer Protocol) é um protocolo que especifica como será a comunicação entre um navegador e um servidor web, sendo um dos principais da World Wide Web
Canaltech

HTTP

REST

Representational State Transfer é um estilo de arquitetura de software que define um conjunto de restrições a serem usadas para a criação de serviços Web
Wikipédia

HTTP

REST

Os Web services que estão em conformidade com o estilo arquitetural REST, denominados RESTful, fornecem interoperabilidade entre sistemas de computadores na Internet
Wikipédia

HTTP

REST

Os Web services RESTful permitem que os sistemas solicitantes acessem e manipulem representações textuais de recursos da Web usando um conjunto uniforme e predefinido de operações sem estado
Wikipédia

HTTP

GraphQL

Linguagem de consulta e ambiente de execução voltada a servidores para as interfaces de programação de aplicações (APIs) cuja prioridade é fornecer exatamente os dados que os clientes solicitam e nada além
RedHat

HTTP

GraphQL

Desenvolvido para tornar as APIs mais rápidas, flexíveis e intuitivas para os desenvolvedores, sendo possível implantá-lo em uma IDE conhecido como GraphiQL
RedHat

HTTP

GraphQL

Como alternativa à arquitetura REST, o GraphQL permite aos desenvolvedores construir solicitações que extraem os dados de várias fontes em uma única chamada de API
RedHat

HTTP

GraphQL

Além disso, o GraphQL proporciona aos profissionais responsáveis pela manutenção das APIs flexibilidade para adicionar ou preterir campos, sem afetar as consultas existentes
RedHat

HTTP

GraphQL

Os desenvolvedores podem criar APIs com o método que quiserem, pois a especificação do GraphQL assegura que elas funcionem de maneira previsível para os clientes
RedHat

HTTP

REST vs GraphQL

REST vs GraphQL

HTTP

REST vs GraphQL

IPC

Interprocess communication é o mecanismo fornecido pelo sistema operacional que permite que os processos se comuniquem entre eles. Esta comunicação pode envolver um processo informando outro processo sobre a ocorrência de um evento ou sobre a transferência de dados de um processo para outro.
TutorialsPoint

IPC

O que é RPC?

Remote Procedure Call (RPC) é uma tecnologia de comunicação entre processos que permite a um programa de computador chamar um procedimento em outro espaço de endereçamento, implementando o modelo cliente-servidor de computação distribuída
Wikipedia

IPC

O que é gRPC?

Framework RPC de alta performance implementado em HTTP/2 que pode rodar em qualquer ambiente

Desenvolvido pelo Google em 2015 como a próxima geração do Stubby e liberado em 2016

Possui suporte para load balancing, tracing, health checking, autenticação e outras funcionalidades

grpc.io

IPC

O que é gRPC?

gRPC
grpc.io/docs/what-is-grpc/introduction

gRPC

O que são “Protocol Buffers”?

Mecanismo agnóstico de linguagem e plataforma para serializar dados estruturados

Semelhante a um Schema, onde definimos como os dados serão estruturados

E com geração automática de código-fonte do servidor e do cliente em diversas linguagens

developers.google.com/protocol-buffers

gRPC

Formatos de Comunicação

  • Unário
  • Streaming do Servidor
  • Streaming do Cliente
  • Streaming Bidirecional

grpc.io/docs/what-is-grpc/core-concepts

Comunicação gRPC

Unário

Formato mais tradicional de comunicação, onde o cliente envia uma requisição e o servidor retorna a resposta

Assim que o cliente invoca o método stub, o servidor é notificado com os metadados do cliente para essa chamada, o nome do método e o timeout (se aplicável)

Comunicação gRPC

Unário

O servidor pode então enviar de volta seus próprios metadados iniciais (que devem ser enviados antes de qualquer resposta) imediatamente ou esperar pela requisição do cliente

Assim que o servidor receber a mensagem de requisição do cliente, ele faz o que for necessário e a resposta é então retornada com o status (código e mensagem opcional) e possíveis metadados finais

Comunicação gRPC

Streaming do Servidor

Cenário onde o servidor retorna um streaming de respostas ao invés de uma única

O cliente completa seu processamento depois que recebe todas as mensagens do servidor

Comunicação gRPC

Streaming do Cliente

Situação onde o cliente envia um streaming de mensagens em uma requisição

O servidor responde com uma única mensagem (com o status e possíveis metadados finais), tipicamente ‐ mas não necessariamente ‐ após ter recebido todas as mensagens do cliente

Comunicação gRPC

Streaming Bidirecional

Onde há streaming de mensagens do Cliente e do Servidor

Nesse caso, cada aplicação pode implementar de sua maneira: o servidor pode responder a cada dado recebido, a cada X mensagens ou esperar até que um dos lados feche a conexão

Mensageria

Mensageria

RabbitMQ

An open-source message-broker software (sometimes called message-oriented middleware) that originally implemented the Advanced Message Queuing Protocol (AMQP) and has since been extended with a plug-in architecture to support Streaming Text Oriented Messaging Protocol (STOMP), MQ Telemetry Transport (MQTT), and other protocols

Mensageria

RabbitMQ

RabbitMQ

Mensageria

Kafka

O Apache Kafka é uma plataforma distribuída de transmissão de dados que é capaz de publicar, subscrever, armazenar e processar fluxos de registro em tempo real. Essa plataforma foi desenvolvida para processar fluxos de dados provenientes de diversas fontes e entregá-los a vários clientes.
Red Hat

Mensageria

Kafka

O Kafka é muito mais que um Message Broker: com uma grande comunidade e muita estabilidade, possui muito mais funcionalidades do que a simples troca de mensagens entre produtores e consumidores
vepo.medium.com

Mensageria

Kafka vs RabbitMQ

kafka vs RabbitMQ
medium.com/@ramekris

Padrões

Padrões

Saga

Saga

Problema

Em um ambiente de microsserviços, algumas requisições precisarão realizar transações entre diversos serviços distintos

Saga

Problema

Como cada microsserviço possui seu próprio banco de dados, precisamos ter uma forma de controlar essas transações, parar o processo assim que houver um erro e fazer os devidos rollbacks em cada um dos serviços

Saga

Conceito

Artigo publicado por Hector Garcia-Molina em 1987, focando em Long-Running Processes

Sequência de transações locais, onde cada transação irá publicar uma mensagem que irá disparar a próxima transação local do serviço seguinte

Saga

Conceito

Se a transação local falhar (por regra de negócio ou outro motivo), serão executadas uma série de transações compensatórias para desfazer as mudanças realizadas até o momento

Saga

Conceito

Normalmente, os registros são primeiro criados com um status Pendente e, após a confirmação das transações seguintes, são alterados para Ativo

Nesse caso, transações compensatórias podem simplesmente alterar esse campo para Inativo

Saga

Conceito

SAGA
docs.microsoft.com

Saga

Coordenando Sagas

Coreografia

Cada transação local publica eventos que irão desencadear transações em outros serviços

Saga

Coordenando Sagas

Coreografia

SAGA - Coreografia

Saga

Coordenando Sagas

Orquestração

Um objeto central (orquestrador) é responsável por invocar cada transação dos serviços

Saga

Coordenando Sagas

Orquestração

SAGA - Orquestração

Saga

Referências

Saga

Exemplo de aplicação

Saga

Padrões

  • C
  • Q
  • S

Padrões

  • C
  • ommand
  • Q
  • uery
  • S
  • eparation

CQS

Conceito

Conceito elaborado por Bertrand Meyer (criador da linguagem Eiffel e do princípio Design by Contract):

Asking a question should not change the answer
Wikipedia

CQS

Conceito

Conceito elaborado por Bertrand Meyer (criador da linguagem Eiffel e do princípio Design by Contract):

Every method should either be a command that performs an action, or a query that returns data to the caller, but not both
Wikipedia

CQS

Exemplo


                            class Employee {
                                public function increaseSalary(float $amount): float {
                                    $this->salary += $amount;
                                    return $this->salary;
                                }
                            }
                        

Exemplo de código comumente encontrado


                            $employee = new Employee();
                            $wage = $employee->getWage();

                            // alguma coisa no script...

                            $employee->increaseSalary(500);
                            // $wage agora está desatualizado
                        

Possível problema

CQS

Exemplo


                            class Employee {
                                public function increaseSalary(float $amount): float {
                                    $this->salary += $amount;
                                    return $this->salary;
                                }
                            }
                        

Exemplo de código comumente encontrado

CQS

Exemplo


                            class Employee {
                                public function increaseSalary(float $amount): void {
                                    $this->salary += $amount;
                                }

                                public function getSalary(): float {
                                    return $this->salary;
                                }
                            }
                        

Exemplo de código refatorado usando CQS

Padrões

  • C
  • Q
  • R
  • S

Padrões

  • C
  • ommand
  • Q
  • uery
  • R
  • esponsibility
  • S
  • egregation

CQRS

Conceito

É um padrão arquitetural descrito pela primeira vez em 2010 por Greg Young

Separação (em objetos distintos) da responsabilidade de escrita e leitura dos dados

CQRS

Conceito

Os Commands precisam demonstrar a intenção do usuário em executar aquela ação

Exemplos: “Cadastrar Endereço”, “Calcular Imposto”, “Adicionar Item ao Carrinho”

CQRS

Exemplo


                            class Employee {
                                public function increaseSalary(float $amount): void {
                                    $this->salary += $amount;
                                }

                                public function getSalary(): float {
                                    return $this->salary;
                                }
                            }
                        

Exemplo visto em CQS

CQRS

Exemplo


                            class IncreaseEmployeeWageCommand {
                                public function __construct(Employee $employee, float $amount) {
                                    // ...
                                }
                            }

                            class EmployeeFinder {
                                // ...
                            }
                        

Exemplo aplicando CQRS

CQRS

Por quê?

Escalar a aplicação tem se tornado cada vez mais comum nos últimos tempos, mas mesmo assim ainda existe um grande gargalo: o banco de dados

Há uma grande complexidade envolvida em escalar bancos de dados — e muitas vezes um alto custo também

CQRS

Por quê?

Além disso, para exibirmos um dado para o cliente, às vezes temos que aplicar várias regras de negócio, realizar JOINs (se usarmos bancos SQL) e outras ações para formatar a informação

Tudo isto pode custar muito tempo e até mesmo causar timeouts, deadlocks e outras situações terríveis para DBAs

CQRS

Por quê?

O uso de bancos NoSQL ajudou em muito ao guardar documentos em formatos um pouco mais parecidos ao que o usuário final irá visualizar

Ainda assim, em uma aplicação comum a frequência de escritas é muito menor do que a de leitura (em proporções até maiores que 80/20%)

CQRS

Por quê?

Então, por que geralmente facilitamos a escrita ao invés da leitura ao arquitetar nossos bancos de dados?

CQRS

Quando usar?

  • Se você possui (ou prevê possuir) problemas de performance no banco de dados;
  • Quando a lógica de negócio for muito complexa para simples CRUDs;
  • E provavelmente em apenas algumas partes de sua aplicação.

CQRS

Modelo de Implementação

1. Comece separando logicamente Commands e Queries em objetos diferentes


                            class EmployeeFinder() {
                            }

                            class IncreaseEmployeeWageCommand {
                                public function __construct(Employee $employee, float $amount) {
                                }
                            }

                            class PromoteEmployeeCommand {
                                public function __construct(Employee $employee, Position $newPosition) {
                                }
                            }
                        

CQRS

Modelo de Implementação

2. Crie uma base de dados somente de leitura e faça seus Commands a atualizarem assim que algo for persistido

CQRS
slideshare.net/gyuwonyi/cqrs-121010087

CQRS

Modelo de Implementação

3. Faça a atualização da base de leitura acontecer de forma assíncrona, para não atrapalhar na performance


Dependendo de sua regra de negócio, você pode começar criando um procedimento recorrente (ex: através do Cron) para atualizar sua base em intervalos de tempo específico

CQRS

Modelo de Implementação

3. Faça a atualização da base de leitura acontecer de forma assíncrona, para não atrapalhar na performance


Mas o mais indicado é utilizar um sistema de filas: ao receber um comando, publique uma mensagem dizendo que o registro X da tabela Y precisa ser atualizado e crie um subscriber que irá executar essa tarefa

CQRS

Modelo de Implementação

4. Se necessário, altere a base de leitura para torná-la uma agregação de dados de diferentes tabelas para entregar à view exatamente o que ela precisa


Esse base também é conhecida como banco de dados desnormalizado e irá agir similarmente a um DTO

CQRS

Modelo de Implementação

5. Utilize sistema de filas para executar os comandos


Ao receber uma requisição, valide minimamente os dados e publique uma mensagem dizendo que o comando X precisa ser executado (com os dados recebidos)

CQRS

Modelo de Implementação

5. Utilize sistema de filas para executar os comandos


Então, crie um subscriber para executar esses comandos e emita uma resposta indicando a finalização

CQRS

Modelo de Implementação

5. Utilize sistema de filas para executar os comandos


Essa resposta pode ser um evento para a UI (dependendo da linguagem que você usa), um email para o usuário ou uma push notification... você também pode trabalhar com long polling, websockets, service workers ou outras abordagens

CQRS

Modelo de Implementação

CQRS
eduardopires.net.br

CQRS

Consistência Eventual

Com essa prática, nosso banco de dados leitura pode ficar alguns segundos (ou até minutos, dependendo da abordagem) desatualizado

E a dúvida é: “Mas essa prática não é ruim?”

CQRS

Consistência Eventual

Temos uma tendência de valorizar demais a consistência de dados, mas a inconsistência é algo muito comum em nosso dia-a-dia — tanto físico quanto virtual

CQRS

Consistência Eventual

Dados podem ser consultados e alterados por usuários simultaneamente conectados

Os dados exibidos em uma tela já podem ter sido alterados por outro usuário

Então é possível afirmar que toda informação exibida já pode estar obsoleta

CQRS

Consistência Eventual

Consistência Eventual - Twitter @gregyoung
Twitter @gregyoung

CQRS

Vantagens

  • Todos comandos são assíncronos e processados em fila, assim diminui-se o tempo de espera

CQRS

Vantagens

  • Os processos que envolvem regras de negócio existem apenas no sentido da inclusão ou alteração do estado das informações

CQRS

Vantagens

  • As consultas são feitas de forma separada e independente e não dependem do processamento dos comandos

CQRS

Vantagens

  • É possível escalar separadamente os processos de execução de comandos e consulta

CQRS

Desvantagens

  • Maior complexidade na aplicação, aumentando o tempo para os primeiros releases (mas potencialmente diminuindo tempos de reescrita no futuro para melhorias de performance)

CQRS

Desvantagens

  • Garantir consistência dos dados torna-se cada vez mais complexo (lembrando do teorema CAP)

CQRS

Desvantagens

  • Usar outros bancos de dados, sistemas de fila e subscribers implicam em mais pontos de falha, necessidade de mais monitoramento e mecanismos de segurança para manter todo o ambiente rodando corretamente

CQRS

Referências

CQRS

Exemplo de Aplicação

CQRS - Escrita

CQRS

Exemplo de Aplicação

CQRS - Escrita

Referências

Obrigado!