Arquitetura de micro-serviços na prática: modelagem e rastreabilidade dos serviços

Marcelo Flores
5 min readNov 17, 2017

--

Abstract

O padrão arquitetural de micro-serviços está sendo adotado cada dia mais por diversas empresas do mercado. Este padrão possui diversas vantagens, como: possibilitar escrever componentes de um único sistema utilizando linguagens diferentes se necessário, facilitar a escalabilidade do sistema, simplificar o deploy de componentes separados do sistema, entre outras. Porém, ele traz também uma série de desafios. Por exemplo, o espalhamento das informações de log e o acompanhamento de transações que representam um único contexto, mas são realizadas em diversos serviços.

Este artigo descreve como migrar uma arquitetura monolítica para uma arquitetura de micro-serviços do integrador de anúncios em massa da OLX Brasil, em conjunto com técnicas para melhorar o acompanhamento do funcionamento sistemas distribuídos e implementados em diversas linguagens de programação.

O sistema

As principais características do integrador são:

  • Gerenciar 200 mil anúncios por dia.
  • Gerenciar um volume de imagens de até 20 vezes a quantidade de anúncios, ou seja até 2 milhões.
  • Inserção de novos anúncios.
  • Edição de anúncios publicados;
  • Remoção de anúncios definidos pelo cliente.
  • Geração de relatórios de carga.

Sistema legado

A versão anterior do sistema está desenhada na figura 1. Este sistema possuía todas as funcionalidades dentro de uma única linguagem de programação, com um deploy para o sistema inteiro.

Figura 1. Sistema legado de integração de anúncios

A nova arquitetura utilizando micro-serviços

A partir da avaliação do sistema legado, escolhemos criar os micro-serviços (Figura 2) de:

  1. Importação/Edição
  2. Remoção
  3. Relatórios

Figura 2. Identificação de micro-serviços do sistema

Arquitetura do importador

Por sua vez, o serviço de importação tinha muitas responsabilidades, então resolvemos separar ele em micro-serviços também (Figura 3).

Figura 3. Micro-serviços de importação

Arquitetura do Mapeador de anúncios e da remoção de anúncios

Como exemplo de um dos serviços, segue o diagrama do mapeador de anúncios (figura 5)

Figura 5. Diagrama do mapeador de anúncios

O serviço diminuiu o escopo de responsabilidades grandemente. O deploy ficou mais simples e, hoje em dia, é possível de ser realizado isoladamente, sem precisar realizar o deploy do sistema inteiro. Outra vantagem é que o pipeline de testes ficou focado apenas na funcionalidade de mapeamento.

Ainda dá para dividir mais o serviço, mas estamos incrementalmente separando as responsabilidades.

Arquitetura da Remoção de anúncios

A remoção de anúncios foi feita em Python (Figura 6). É possível realizar ajustes na remoção sem precisar alterar nada no mapeador ou inserção. Mudanças são focadas e mais diretas.

Figura 6. Remoção de anúncios

Desafios dos micro-serviços

Um dos grandes desafios que enfrentamos é o espalhamento da informação entre os serviços. Apesar deles serem independentes, é bom lembrar que eles compõem um único sistema. Isto significa que o suporte precisa ter visibilidade do que acontece com o anúncio de forma transparente. Os clientes também querem saber de forma consolidada o que acontece com seus anúncios, se foram removidos, se tem algum problema na carga, mapeamento, remoção, etc.

Para conseguir unificar as saídas dos logs de cada componente do sistema escolhemos o stack ELK. Nele inserimos as ações de cada um deles, para futuramente ter uma visão consolidada dos dados.

Uma estratégia que é muito útil nesse caso é a padronização de logs e posterior consolidação no ElasticSearch via post de cada evento de log.

Cada componente pode estar até em linguagens diferentes, mas qualquer linguagem de programação é capaz de gerar um formato padrão, que identifique as operações universalmente.

Escolhemos 2 chaves para identificar cada linha de log: Id do usuário e Id do anúncio. Por exemplo, podemos modelar os logs da seguinte forma:

# Log da importação em Java

[INFO][2017/08/31 01:36:10][Ad] [main][alianca@aliancaimoveis.net][LOC32041] New ad imported

# Log do mapeador em Perl

[INFO][2017/08/31 11:33:05][Mapper] [main][alianca@aliancaimoveis.net][LOC32041] Mapped Rooms = 3

Os campos em negrito representam a chave primária e secundária das operações. Isto permite que possamos ter campos em comum, que permitem realizar buscas de todas as operações em qualquer parte do sistema, independente da procedência

Consultas das transações transversalmente (Figura 7):

Figura 7. Consultas realizadas no Kibana

O Stack ELK

O stack (Figura 8) se compõe de: logstash (parseamento e envio dos registros de log), elastic search (indexador), kibana (visualizador).

Figura 8. Stack ELK

O envio dos logs pode ser realizado diretamente da própria aplicação para o elastic search através das APIs internas dele. Porém, escolhemos enviar a informação de log parseando utilizando logstash, alimentado com filebeat (Figura 9).

Figura 9. Envio de logs utilizando filebeat

Conclusões

Nossa experiência tem sido bem positiva com a migração de responsabilidades para diversos componentes ou micro-serviços. A divisão correta de cada serviço é muito importante para o sucesso. Por isso, identifique as responsabilidades muito bem antes de dividir.

Podemos citar as seguintes vantagens da arquitetura com micro-serviços:

  • O deploy fica extremamente mais leve e simples.
  • A complexidade fica reduzida, pois cada serviço possui um escopo menor do que um monolito. O volume de log pode ser grande, escolha bem o que você quer consultar.
  • Não tudo precisa ser inserido no log.
  • Cada linha do log precisa identificar o escopo, independente da linguagem. Estamos trabalhando com processos em paralelo.
  • Ter um log padronizado entre serviços/linguagens diferentes permite gerar relatórios consolidados entre eles, traceability.

--

--