Construindo a NuConta · Dinheiro recebido do Banco Central Integração com o Banco Central....

Post on 30-Jul-2020

7 views 0 download

Transcript of Construindo a NuConta · Dinheiro recebido do Banco Central Integração com o Banco Central....

Gustavo BicalhoMaurício Verardo

Construindo a NuConta

Agenda

● NuConta● Microsserviços no Nubank● Transferindo dinheiro entre NuContas

○ Event-sourcing: Modularidade e Escalabilidade○ Consistência em sistemas distribuídos

● O feed de movimentações○ Backend for Frontends com GraphQL

NuConta

NuConta

NuConta

NuConta

NuConta

NuConta

NuConta

NuConta

https://nubank.design/

Microsserviços

Microsserviços

Fatura

Saldo

AntecipaçãoAntecipações

Saldos

Faturas

Saldos

Antecipações

Faturas

Microsserviços

Fatura

Saldo

Antecipação

Load

Balancer

Load

Balancer

Load

Balancer

Microsserviços

Serviço A Serviço BHTTP

Microsserviços

Serviço A

Tópico do Kafka

Serviço B

Transferindo dinheiro entre NuContas

SOUTHEAST BRAZIL REGION FROM SPACE

Transferindo dinheiro entre NuContas

Pedido de envio

Envio

Recebimentos

Recebimento

Envios

Liquidação

Saldos

Depósito

Transferindo dinheiro entre NuContas

Pedido de envio

RecebimentosEnvios

Saldos

Pedido

Envio Solicitado

Transferindo dinheiro entre NuContas

Pedido de envio

RecebimentosEnvios

Saldos

Pedido

Envio Solicitado

Liquidação

Liquidação efetuada

Transferindo dinheiro entre NuContas

Pedido de envio

RecebimentosEnvios

Saldos

Pedido

Envio Solicitado

Liquidação

Envio

Liquidação efetuada

Dinheiro enviado para NuConta

Transferindo dinheiro entre NuContas

Pedido de envio

RecebimentosEnvios

Saldos

Pedido

Envio Solicitado

Liquidação

Envio

Liquidação efetuada

Dinheiro enviado para NuConta

Recebimento

Dinheiro Recebido

Transferindo dinheiro entre NuContas

Pedido de envio

RecebimentosEnvios

Saldos

Pedido

Envio Solicitado

Liquidação

Envio

Liquidação efetuada

Dinheiro enviado para NuConta

Recebimento

Dinheiro Recebido

Depósito

Características interessantes desse fluxo

Pedido de envio

RecebimentosEnvios

Saldos

Pedido

Envio Solicitado

Liquidação

Envio

Liquidação efetuada

Dinheiro enviado para NuConta

Recebimento

Dinheiro Recebido

Depósito

Event Sourcing

Pedido de envio

RecebimentosEnvios

Saldos

Pedido

Envio Solicitado

Liquidação

Envio

Liquidação efetuada

Dinheiro enviado para NuConta

Recebimento

Dinheiro Recebido

Depósito

E se o cliente quiser enviar transferências para outra instituição financeira?

Pedido de envio

Envios

Saldos

Pedido

Envio Solicitado

Liquidação

Envio

Liquidação efetuada

Depósito

E se o cliente quiser enviar transferências para outra instituição financeira?

Dinheiro enviado para outra instituição

Integração com o banco central

Pedido de envio

RecebimentosEnvios

Saldos

Pedido

Envio Solicitado

Liquidação

Envio

Liquidação efetuada

Dinheiro enviado para NuConta

Recebimento

Dinheiro Recebido

Depósito

E se o cliente receber transferências de outra instituição financeira?

Recebimentos

Saldos

Liquidação

Recebimento

Dinheiro Recebido

Depósito

E se o cliente receber transferências de outra instituição financeira?

Dinheiro recebido do Banco Central

Integração com o Banco Central

Pedido de envio

RecebimentosEnvios

Saldos

Pedido

Envio Solicitado

Liquidação

Envio

Liquidação efetuada

Dinheiro enviado para NuConta

Recebimento

Dinheiro Recebido

Depósito

E se o cliente quiser pagar a fatura do cartão de crédito?

Pedido de Pagamento

Pagamento de Fatura

Saldos

Pedido

Pagamento Solicitado

Liquidação

Pagamento

Liquidação efetuada

Pagamento de fatura

Depósito

E se o cliente quiser pagar a fatura do cartão de crédito?

Cartão de crédito

Saldos

Liquidação

Depósito

Event Sourcing

Saldo hoje

Saldo no ano que vem

Saldo no mês passado

Pedido de envio

RecebimentosEnvios

Saldos

Pedido

Envio Solicitado

Liquidação

Envio

Liquidação efetuada

Dinheiro enviado para NuConta

Recebimento

Dinheiro Recebido

Depósito

Event Sourcing

Consistência em sistemas distribuídos

O que pode dar errado?

Pedido de envio

Envios

Liquidação

Saldos

Envio Solicitado

Envio

Liquidação para envio

Recebimentos

Recebimento

Dinheiro enviado para NuConta

Dinheiro Recebido

Depósito

Pedido

O que pode dar errado?

Pedido de envio

Envios

Saldos

Envio Solicitado

Envio

Liquidação para envio

Recebimentos

Recebimento

Dinheiro enviado para NuConta

Dinheiro Recebido

DepósitoLiquidação

Pedido

Primeiro requisito: Processamento at-least-once

Todo evento publicado é recebido e processadocompletamente pelos consumidores pelo menos uma vez

Primeiro requisito: Processamento at-least-once

MSG

OK!

:)

MSG

MSG

MSG

Primeiro requisito: Processamento at-least-once

● Mensagens são persistidas e replicadas no Kafka cluster, podendo ser consumidas a qualquer momento

● Próxima mensagem da fila será entregue de novo até que consumidor confirme que completou seu processamento

● Consumidor só deve confirmar o processamento depois que completar todos os efeitos colaterais

Segundo requisito: Idempotência

● Uma operação é idempotente se aplicá-la várias vezes é equivalente a aplicá-la uma vez

● Exemplos:○ Multiplicação por 0: 7*0 = 7*0*0 = 7*0*0*0 … = 0○ DELETE FROM users WHERE users.id = 186

Segundo requisito: Idempotência

● Cada evento em nossa arquitetura tem um UUID aleatório● Cada evento derivado usa o UUID do evento anterior (origem) como chave

única (chave de idempotência)● Serviços garantem consistência interna: banco de dados local valida a chave

única● Resultado: Criar um evento a partir de outro é uma operação idempotente

LiquidacaoID: 78Origem: PedidoDeEnvio:32

PedidoDeEnvioID: 32

Segundo requisito: Idempotência

LiquidacaoID: 78Origem: PedidoDeEnvio:32

PedidoDeEnvioID: 32

EnvioID: 44Origem: Liquidacao:78

RecebimentoID: 156Origem: Envio:44

DepositoID: 377Origem: Recebimento:156

E quando um serviço cair?

Envios

Saldos

Pedido de envio

Envio Solicitado

Liquidação

Pedido

E quando um serviço cair?

Envios

Saldos

Pedido de envio

Liquidação

Envio Solicitado

Pedido

E se rolar um bug ou mensagem inválida?

Envio

SaldosDeadletters

xkcd.com (CC BY-NC 2.5)

Deadletters:Tópico onde guardamos mensagens cujo processamento falhou (inclui metadados como stack-traces, timestamp, etc)

Pedido de envio

Liquidação

Envio Solicitado

Pedido

E se rolar um bug ou mensagem inválida?

Envio

SaldosDeadletters

xkcd.com (CC BY-NC 2.5)

Republicar

/dev/null

Descartar

Deadletters:Tópico onde guardamos mensagens cujo processamento falhou (inclui metadados como stack-traces, timestamp, etc)

Pedido de envio

Liquidação

Envio Solicitado

Pedido

Feed de movimentações

Dados distribuídos = muitos requests

EnviosPedido de envioEnvio

Recebimentos Recebimento

SaldosDepósitoLiquidação

Evento de envio no feed● Valor● Data● Status: pendente | falha | sucesso

Modelo do backend != visão do cliente

Liquidação Envio

404 | 404

404

EnviosPedido de envioEnvio

SaldosLiquidação

● Lançar uma nova versão de um aplicativo numa app store pode demorar dias

● Muitos usuários continuam com versões antigas por muito tempo

● Bugfixes e otimizações demoram para chegar

● Frontend acoplado impede evoluções no backend

Ciclos de atualização lentos

Backend For Frontend

BFF

EnviosPedido de envioEnvio

Recebimentos Recebimento

SaldosDepósitoLiquidação

"GraphQL is a query language designed to build client applications by providing an intuitive and flexible syntax and system for describing their data requirements and

interactions."

(GraphQL spec: http://facebook.github.io/graphql/)

Schema é o modelo disponível para o frontend

schema { query: Query}

type Query { saldo(accountId: ID!): Float feed(accountId: ID!): [Envio | Recebimento]}

type Recebimento { data: Date valor: Float}

enum StatusEnvio { PENDENTE, FALHA, SUCESSO}

type Envio { data: Date valor: Float status: StatusEnvio}

EnviosPedido de envioEnvio

Recebimentos Recebimento

SaldosDepósitoLiquidação

Query define os campos que o client precisa

schema { query: Query}

type Query { saldo(accountId: ID!): Float feed(accountId: ID!): [Envio | Recebimento]}

type Recebimento { data: Date valor: Float}

enum StatusEnvio { PENDENTE, FALHA, SUCESSO}

type Envio { data: Date valor: Float status: StatusEnvio}

query feedScreen($accountId: ID!) {

feed(accountId: $accountId) {

... on Envio { data valor status }

... on Recebimento { data valor }

}

}

POST /api/query

Query define os campos que o client precisa

schema { query: Query}

type Query { saldo(accountId: ID!): Float feed(accountId: ID!): [Envio | Recebimento] saldoDetalhado(accountId: ID!): SaldoDetalhado}

query($accountId: ID!) { feed(accountId: $accountId) { … } saldoDetalhado(accountId: $accountId) { … }}

Client v2

query($accountId: ID!) { feed(accountId: $accountId) { … } saldo(accountId: $accountId)}

Client v1

Recapitulando

● Event-sourcing

● Comunicação assíncrona via Kafka

● Backend for Frontend com GraphQL

Gustavo BicalhoMaurício Verardo

Obrigado!

https://sou.nu/vagasnu