História da arquitetura Dodo IS: o caminho do Back Office

Habr está mudando o mundo. Estamos blogando há mais de um ano. Há cerca de seis meses, recebemos um feedback bastante lógico dos residentes de Khabrovsk: “Dodo, você diz em todos os lugares que tem seu próprio sistema. Que tipo de sistema é esse? E por que a rede de pizzarias precisa disso?”

Sentamos e pensamos e percebemos que você está certo. Tentamos explicar tudo com os dedos, mas sai em pedaços e não há descrição completa do sistema em lugar nenhum. Assim começou uma longa jornada de coleta de informações, busca de autores e redação de uma série de artigos sobre Dodo IS. Vamos!

Agradecimentos: Obrigado por compartilhar seu feedback conosco. Graças a ele finalmente descrevemos o sistema, compilamos um technoradar e em breve lançaremos uma grande descrição de nossos processos. Sem você, teríamos ficado assim por mais 5 anos.

História da arquitetura Dodo IS: o caminho do Back Office

Série de artigos "O que é Dodo IS?" fala sobre:

  1. Monólito inicial em Dodo IS (2011-2015). (Em andamento...)
  2. Caminho de backoffice: bases e barramento separados. (Você está aqui)
  3. O caminho do lado do cliente: fachada sobre a base (2016-2017). (Em andamento...)
  4. A história dos verdadeiros microsserviços. (2018-2019). (Em andamento...)
  5. Serração finalizada do monólito e estabilização da arquitetura. (Em andamento...)

Se você estiver interessado em aprender mais alguma coisa, escreva nos comentários.

Opinião sobre a descrição cronológica do autor
Realizo regularmente reuniões para novos funcionários sobre o tema “Arquitetura de Sistemas”. Chamamos isso de “Introdução à Arquitetura Dodo IS” e faz parte do processo de integração para novos desenvolvedores. Falando de uma forma ou de outra sobre a nossa arquitetura, sobre suas características, desenvolvi uma certa abordagem histórica para a descrição.

Tradicionalmente, vemos um sistema como um conjunto de componentes (técnicos ou de nível superior), módulos de negócios que interagem entre si para atingir algum objetivo. E embora tal visão seja justificada para o design, não é inteiramente adequada para descrição e compreensão. Existem vários motivos:

  • A realidade é diferente do que está no papel. Nem tudo funciona como planejado. E estamos interessados ​​​​em saber como tudo realmente aconteceu e funciona.
  • Apresentação consistente de informações. Na verdade, você pode ir cronologicamente desde o início até o estado atual.
  • Do simples ao complexo. Não é universal, mas no nosso caso é assim. A arquitetura passou de abordagens mais simples para abordagens mais complexas. Muitas vezes, por complicação, surgem problemas de velocidade e estabilidade de implementação, além de dezenas de outras propriedades da lista de requisitos não funcionais (aqui bem falado sobre contrastar a complexidade com outros requisitos).

Em 2011, a arquitetura do Dodo IS era assim:

História da arquitetura Dodo IS: o caminho do Back Office

Em 2020, ficou um pouco mais complicado e ficou assim:

História da arquitetura Dodo IS: o caminho do Back Office

Como aconteceu essa evolução? Por que são necessárias diferentes partes do sistema? Que decisões arquitetônicas foram tomadas e por quê? Vamos descobrir nesta série de artigos.

Os primeiros problemas de 2016: por que os serviços deveriam sair do monólito?

Os primeiros artigos da série serão sobre os serviços que foram os primeiros a se separarem do monólito. Para contextualizar, vou contar quais problemas tivemos no sistema no início de 2016, que tivemos que lidar com a separação de serviços.

Um único banco de dados MySql no qual todos os aplicativos que existiam naquela época no Dodo IS escreviam seus registros. As consequências foram:

  • Carga pesada (com 85% das solicitações sendo lidas).
  • A base estava crescendo. Por causa disso, custo e suporte tornaram-se um problema.
  • Ponto unico de falha. Se um aplicativo gravando no banco de dados repentinamente começasse a fazê-lo de forma mais ativa, outros aplicativos sentiriam o impacto.
  • Ineficiência no armazenamento e consultas. Freqüentemente, os dados eram armazenados em alguma estrutura conveniente para alguns cenários, mas não para outros. Os índices aceleram algumas operações, mas podem retardar outras.
  • Alguns dos problemas foram resolvidos por caches feitos às pressas e réplicas de leitura de bancos de dados (isso será discutido em um artigo separado), mas eles apenas nos permitiram ganhar tempo e não resolveram fundamentalmente o problema.

O problema era a presença do próprio monólito. As consequências foram:

  • Lançamentos únicos e raros.
  • A dificuldade está no desenvolvimento colaborativo de um grande número de pessoas.
  • Incapacidade de introduzir novas tecnologias, novas estruturas e bibliotecas.

Problemas com a base e o monólito foram descritos muitas vezes, por exemplo, no contexto de falhas no início de 2018 (Seja como Munch, ou algumas palavras sobre dívida técnica, O dia em que Dodo IS parou. Script assíncrono и A história do pássaro Dodô da família Phoenix. A Grande Queda do Dodô IS), então não vou me alongar muito. Deixe-me apenas dizer que queríamos dar mais flexibilidade no desenvolvimento de serviços. Em primeiro lugar, tratava-se daqueles que eram mais carregados e rooteados em todo o sistema - Auth e Tracker.

O Caminho do Back Office: Bases e Barramento Separados

Navegação no capítulo

  1. Esquema do monólito 2016
  2. Começamos a descarregar o monólito: separação de Auth e Tracker
  3. O que o Auth faz?
  4. De onde vêm as cargas?
  5. Descarregando autenticação
  6. O que o Rastreador faz?
  7. De onde vêm as cargas?
  8. Descarregando o Rastreador

Esquema do monólito 2016

Aqui estão os principais blocos do monólito Dodo IS 2016, e logo abaixo está uma análise de suas principais tarefas.
História da arquitetura Dodo IS: o caminho do Back Office
Caixa de entrega. Contabilização de transportadores, emissão de ordens para transportadores.
Centro de contato. Aceitando pedidos através da operadora.
Local. Nossos sites (dodopizza.ru, dodopizza.co.uk, dodopizza.by, etc.).
Auth. Serviço de autorização e autenticação para backoffice.
Rastreador. Rastreador de pedidos de cozinha. Serviço para marcação de status de prontidão na preparação de um pedido.
Caixa do restaurante. Recebendo pedidos em um restaurante, interfaces de caixa.
Exportações. Carregando relatórios em 1C para contabilidade.
Alertas e faturas. Comandos de voz na cozinha (por exemplo, “Chegou pizza nova”) + impressão de faturas para entregadores.
Gerente de turno. Interfaces para o trabalho de um gerente de turno: lista de pedidos, gráficos de produtividade, encaminhamento de funcionários para turnos.
Gerente. Interfaces para trabalho de franqueados e gestores: recepção de funcionários, relatórios sobre o trabalho da pizzaria.
Quadro de restaurante. Exibição de cardápios em TVs de pizzarias.
Administrador. Configurações de uma pizzaria específica: cardápio, preços, contabilização, códigos promocionais, promoções, banners do site, etc.
Conta Pessoal do Funcionário. Horários de trabalho dos funcionários, informações sobre os funcionários.
Quadro de motivação para cozinha. Uma tela separada que fica pendurada na cozinha e mostra a velocidade dos pizzarias.
Comunicação. Envio de sms e e-mail.
Armazenamento de arquivo. Serviço próprio de recebimento e emissão de arquivos estáticos.

As primeiras tentativas de resolver problemas ajudaram-nos, mas foram apenas uma trégua temporária. Elas não se tornaram soluções sistêmicas, então ficou claro que algo precisava ser feito com as bases. Por exemplo, divida o banco de dados geral em vários bancos mais especializados.

Começamos a descarregar o monólito: separação de Auth e Tracker

Os principais serviços que escreveram e leram mais do banco de dados do que outros:

  1. Autorização Serviço de autorização e autenticação para backoffice.
  2. Rastreador. Rastreador de pedidos de cozinha. Serviço para marcação de status de prontidão na preparação de um pedido.

O que o Auth faz?

Auth é um serviço através do qual os usuários fazem login no back office (há um login independente separado no lado do cliente). Também é referenciado na solicitação para garantir que os direitos de acesso corretos estejam presentes e que esses direitos não tenham sido alterados desde o último login. Aparelhos entram nas pizzarias por ele.

Por exemplo, queremos abrir um display com o status dos pedidos concluídos na TV pendurada no corredor. Em seguida, abrimos auth.dodopizza.ru, selecionamos “Login como dispositivo”, aparece um código que pode ser inserido em uma página especial no computador do gerente de turno, indicando o tipo de dispositivo (dispositivo). A própria TV irá até a interface desejada de sua pizzaria e começará a exibir ali os nomes dos clientes cujos pedidos estão prontos.

História da arquitetura Dodo IS: o caminho do Back Office

De onde vêm as cargas?

Cada usuário de backoffice logado vai ao banco de dados para cada solicitação, à tabela de usuários, retira o usuário de lá através de uma consulta sql e verifica se ele possui os acessos e direitos necessários para esta página.

Cada um dos dispositivos faz o mesmo apenas com a tabela de dispositivos, verificando sua função e seus acessos. Um grande número de solicitações ao banco de dados mestre leva ao seu carregamento e ao desperdício de recursos gerais do banco de dados nessas operações.

Descarregando autenticação

Auth possui um domínio isolado, ou seja, dados sobre usuários, logins ou dispositivos entram no serviço (atualmente futuro) e lá permanecem. Se alguém precisar deles, ele irá a este serviço para obter dados.

ERA. O fluxo de trabalho era inicialmente assim:

História da arquitetura Dodo IS: o caminho do Back Office

Gostaria de explicar um pouco como funcionou:

  1. Uma solicitação externa chega ao backend (Asp.Net MVC lá), trazendo consigo um cookie de sessão, que é usado para obter dados de sessão do Redis(1). Ele contém informações sobre os acessos, e então o acesso ao controlador é aberto (3,4), ou não.
  2. Caso não haja acesso, será necessário passar pelo procedimento de autorização. Aqui, para simplificar, é mostrado como parte do caminho no mesmo atributo, embora seja uma transição para a página de login. No caso de um cenário positivo, receberemos uma sessão preenchida corretamente e iremos para o Backoffice Controller.
  3. Se houver dados, você precisará verificar a relevância deles no banco de dados do usuário. Sua função mudou, ele não deveria ser permitido na página agora? Neste caso, após receber a sessão (1), é necessário ir diretamente ao banco de dados e verificar o acesso do usuário através da camada lógica de autenticação (2). Em seguida, vá para a página de login ou vá para o controlador. Este é um sistema simples, mas não totalmente padrão.
  4. Se todos os procedimentos forem concluídos, avançamos na lógica dos controladores e métodos.

Os dados do usuário são separados de todos os outros dados, são armazenados em uma tabela de membros separada e as funções da camada lógica AuthService podem muito bem se tornar métodos de API. Os limites do domínio são definidos de forma bastante clara: usuários, suas funções, dados de acesso, emissão e revogação de acesso. Parece que tudo pode ser movido para um serviço separado.

TORNOU-SE. Isso é o que eles fizeram:

História da arquitetura Dodo IS: o caminho do Back Office

Esta abordagem tem vários problemas. Por exemplo, chamar um método dentro de um processo não é o mesmo que chamar um serviço externo via http. Latência, confiabilidade, capacidade de suporte e transparência da operação são completamente diferentes. Andrey Morevsky falou com mais detalhes exatamente sobre esses problemas em seu relatório "50 tons de microsserviços".

O serviço de autenticação e com ele o serviço de dispositivo são utilizados para back office, ou seja, para serviços e interfaces utilizados na produção. A autenticação para serviços de cliente (como um site ou aplicativo móvel) ocorre separadamente, sem usar Auth. A separação durou cerca de um ano, e agora estamos trabalhando novamente nesse tema, transferindo o sistema para novos serviços de autenticação (com protocolos padrão).

Por que a separação demorou tanto?
Houve muitos problemas ao longo do caminho que nos atrasaram:

  1. Queríamos transferir dados sobre usuários, dispositivos e autenticação de bancos de dados de países para um só. Para fazer isso, tivemos que transferir todas as tabelas e usos do identificador int para o identificador UUId global (reformulamos este código recentemente Roman Bukin “Uuid - a grande história de uma pequena estrutura” e projeto de código aberto Primitivos). O armazenamento de dados do usuário (por se tratar de informações pessoais) tem suas limitações e para alguns países é necessário armazená-los separadamente. Mas deve haver um ID de usuário global.
  2. Muitas tabelas no banco de dados possuem informações de auditoria sobre o usuário que executou a operação. Isto exigiu um mecanismo adicional para garantir a consistência.
  3. Após a criação dos serviços API, houve um longo e gradual período de transferência para outro sistema. As trocas precisavam acontecer de maneira integrada para os usuários e exigiam trabalho manual.

Esquema de cadastro de aparelho em pizzaria:

História da arquitetura Dodo IS: o caminho do Back Office

Arquitetura geral após separar o serviço Auth e Devices:

História da arquitetura Dodo IS: o caminho do Back Office

Nota. Para 2020, estamos trabalhando em uma nova versão do Auth, que se baseia no padrão de autorização OAuth 2.0. Este padrão é bastante complexo, mas útil para desenvolver um serviço de autenticação ponta a ponta. No artigo "Sutilezas de autorização: visão geral da tecnologia OAuth 2.0» nós, Alexey Chernyaev, tentamos falar sobre o padrão da maneira mais simples e clara possível para que você economize tempo em estudá-lo.

O que o Rastreador faz?

Agora, sobre o segundo dos serviços carregados. O rastreador desempenha uma função dupla:

  • Por um lado, a sua função é mostrar aos colaboradores da cozinha quais os pedidos que estão em curso, quais os produtos que precisam de ser preparados agora.
  • Por outro lado, digitalize todos os processos da cozinha.

História da arquitetura Dodo IS: o caminho do Back Office

Quando um novo produto (por exemplo, pizza) aparece em um pedido, ele vai para a estação rastreadora “Rolling”. Nesta estação há um pizzaiolo que pega um pão do tamanho desejado e o estende, após o que marca no tablet rastreador que completou sua tarefa e passa a base de massa enrolada para a próxima estação - “Recheio” .

Lá, o próximo pizzaiolo cobre a pizza, marca no tablet que completou sua tarefa e coloca a pizza no forno (esta também é uma estação separada que precisa ser marcada no tablet). Tal sistema esteve presente desde o início no Dodo e desde o início do Dodo IS. Ele permite rastrear e digitalizar totalmente todas as operações. Além disso, o rastreador sugere como preparar um determinado produto, realiza cada tipo de produto de acordo com seus próprios esquemas de fabricação, armazena o tempo ideal de cozimento do produto e rastreia todas as operações no produto.

História da arquitetura Dodo IS: o caminho do Back OfficeEsta é a aparência da tela do tablet na estação rastreadora Raskatka.

De onde vêm as cargas?

Cada pizzaria possui cerca de cinco tablets com rastreador. Em 2016 tínhamos mais de 100 pizzarias (e agora são mais de 600). Cada um dos tablets faz uma solicitação ao backend a cada 10 segundos e coleta dados da tabela de pedidos (link com o cliente e endereço), da composição do pedido (link com o produto e indicação de quantidade) e da tabela de motivação (rastreia o momento de pressionar). Quando um pizzaiolo clica em um produto do rastreador, os registros de todas essas tabelas são atualizados. A tabela de pedidos é geral; contém simultaneamente inserções ao aceitar um pedido, atualizações de outras partes do sistema e inúmeras leituras, por exemplo, em uma TV pendurada em uma pizzaria e mostrando pedidos prontos aos clientes.

Durante o período de luta com cargas, quando tudo e todos eram armazenados em cache e transferidos para uma réplica assíncrona do banco de dados, essas operações com o rastreador continuavam a ir para o banco de dados mestre. Não deve haver atraso aqui, os dados devem estar atualizados, fora de sincronia é inaceitável.

Além disso, a falta de tabelas e índices próprios não nos permitiu escrever consultas mais específicas e adaptadas para nosso uso. Por exemplo, pode ser eficaz para um rastreador ter um índice de uma pizzaria em sua tabela de pedidos. Sempre coletamos pedidos de pizzarias do banco de dados do rastreador. Ao mesmo tempo, para aceitar um pedido não é tão importante a que pizzaria ele se enquadra, o mais importante é qual cliente fez esse pedido. Isso significa que precisa haver um índice no cliente. Também não é necessário que o rastreador armazene o id do recibo impresso ou das promoções de bônus associadas ao pedido na tabela de pedidos. Nosso serviço de rastreamento não está interessado nesta informação. Em um banco de dados monolítico comum, as tabelas só poderiam ser um compromisso entre todos os usuários. Este foi um dos problemas originais.

ERA. Inicialmente a arquitetura era assim:

História da arquitetura Dodo IS: o caminho do Back Office

Mesmo depois de ser separado em processos separados, a maior parte da base de código permaneceu comum a diferentes serviços. Tudo abaixo dos controladores foi unificado e residia em um repositório. Foram utilizados métodos comuns de serviços, repositórios e um banco de dados comum contendo tabelas comuns.

Descarregando o Rastreador

O principal problema do rastreador é que os dados devem ser sincronizados entre diferentes bancos de dados. Esta é também a sua principal diferença em relação à divisão do serviço Auth, o pedido e o seu estado podem mudar e devem ser apresentados em vários serviços.

Aceitamos pedidos no Checkout do Restaurante (este é um serviço), o mesmo fica armazenado na base de dados no estado “Aceito”. Depois disso, deverá ir para o rastreador, onde mudará seu status mais várias vezes: de “Cozinha” para “Embalado”. Neste caso, algumas influências externas da interface do Caixa ou do Gerente de Turno podem ocorrer com o pedido. Darei os status dos pedidos com suas descrições na tabela:

História da arquitetura Dodo IS: o caminho do Back Office
O esquema de alteração do status do pedido é semelhante a este:

História da arquitetura Dodo IS: o caminho do Back Office

Os status mudam entre diferentes sistemas. E aqui o rastreador não é o sistema final no qual os dados são bloqueados. Vimos várias abordagens possíveis para separação nesse caso:

  1. Concentramos todas as ações de pedidos em um só atendimento. No nosso caso, esta opção requer muito serviço para processar o pedido. Se tivéssemos parado por aí, teríamos acabado com um segundo monólito. Não teríamos resolvido os problemas.
  2. Um sistema faz uma chamada para outro. A segunda opção é mais interessante. Mas com isso, cadeias de chamadas são possíveis (falhas em cascata), a conectividade dos componentes é maior e é mais difícil de gerenciar.
  3. Organizamos eventos, e cada serviço troca com o outro através desses eventos. Com isso, foi escolhida a terceira opção, segundo a qual todos os serviços passam a trocar eventos entre si.

O facto de termos escolhido a terceira opção significava que o rastreador teria uma base de dados própria, e a cada alteração na ordem enviaria um evento sobre isso, ao qual seriam subscritos outros serviços e que também seriam incluídos na base de dados master. Para fazer isso, precisávamos de algum serviço que garantisse a entrega de mensagens entre serviços.

Naquela época, já tínhamos o RabbitMQ na pilha, daí a decisão final de usá-lo como corretor de mensagens. O diagrama mostra a transição de um pedido do Caixa do Restaurante através do Rastreador, onde altera seu status e sua exibição na interface de Pedidos do Gerente. AÇO:

História da arquitetura Dodo IS: o caminho do Back Office

Caminho do pedido passo a passo
O caminho do pedido começa em um dos serviços de origem do pedido. Aqui está o caixa do restaurante:

  1. O pedido fica totalmente pronto no Checkout e é hora de enviá-lo ao rastreador. O evento no qual o rastreador está inscrito é lançado.
  2. O rastreador, ao aceitar um pedido, salva-o em seu próprio banco de dados, realizando o evento “Pedido Aceito pelo Rastreador” e enviando para a RMQ.
  3. Vários manipuladores já estão inscritos no barramento de eventos customizado. Para nós, é importante aquele que sincroniza com o banco de dados monolítico.
  4. O manipulador recebe o evento, seleciona dele os dados que são significativos para ele: no nosso caso, este é o status do pedido “Aceito pelo Rastreador” e atualiza sua entidade de pedido no banco de dados principal.

Se alguém precisar de um pedido especificamente da tabela de pedidos monolíticos, também poderá lê-lo a partir daí. Por exemplo, é disso que a interface Pedidos no Gerenciador de turnos precisa:

História da arquitetura Dodo IS: o caminho do Back Office

Todos os outros serviços também podem assinar eventos de pedido do rastreador para usá-los por conta própria.

Se após algum tempo um pedido for colocado em produção, seu status primeiro muda em seu banco de dados (banco de dados Tracker), e então o evento “OrderInWork” é gerado imediatamente. Também entra no RMQ, de onde é sincronizado em um banco de dados monolítico e entregue a outros serviços. Pode haver vários problemas ao longo deste caminho; mais detalhes sobre eles podem ser encontrados no relatório de Zhenya Peshkov sobre os detalhes de implementação de Eventual Consistency no Tracker.

Arquitetura final após alterações no Auth e Tracker

História da arquitetura Dodo IS: o caminho do Back Office

Para resumir: Inicialmente, tive a ideia de agrupar a história de nove anos do sistema Dodo IS em um artigo. Queria falar de forma rápida e simples sobre os estágios da evolução. Porém, ao sentar para estudar o material, percebi que tudo é muito mais complexo e interessante do que parece.

Refletindo sobre os benefícios (ou a falta deles) desse material, cheguei à conclusão de que o desenvolvimento contínuo é impossível sem crônicas completas dos acontecimentos, retrospectivas detalhadas e análise das decisões passadas.

Espero que você tenha achado útil e interessante conhecer nossa jornada. Agora me deparo com a escolha de qual parte do sistema Dodo IS descrever no próximo artigo: escreva nos comentários ou vote.

Apenas usuários registrados podem participar da pesquisa. Entrarpor favor

Que parte do Dodo IS você gostaria de aprender no próximo artigo?

  • 24,1%Monólito inicial em Dodo IS (2011-2015)14

  • 24,1%Primeiros problemas e suas soluções (2015-2016)14

  • 20,7%Trajeto da peça cliente: fachada acima da base (2016-2017)12

  • 36,2%História dos microsserviços reais (2018-2019)21

  • 44,8%Corte concluído do monólito e estabilização da arquitetura26

  • 29,3%Sobre planos futuros para o desenvolvimento do sistema17

  • 19,0%Não quero saber nada sobre o Dodo IS11

58 usuários votaram. 6 usuários se abstiveram.

Fonte: habr.com

Adicionar um comentário