Back-End

11 jul, 2017

Distribuindo serviços críticos ao negócio

Publicidade

Dentro da KingHost, criamos várias aplicações web, seja para nós mesmos ou para o uso de clientes, hoje basicamente todas as aplicações são desenvolvidas internamente. Uma dessas aplicações, que por sinal é de vital importância para nós, é o nosso carrinho de compras. Ele é um sistema desenvolvido internamente, que cuida basicamente de todas as vendas de produtos da empresa. Até então, ele era totalmente acoplado ao site e, independentemente de onde era ofertado o produto, o cliente era encaminhado para o carrinho no site para fechar a compra – exceto em algumas exceções, como por exemplo, em compras pós-pagas dentro do painel de controle. Sendo assim, o nosso carrinho era bastante centralizado, o que já é um ponto negativo. Como se não bastasse, além de vender o produto, o carrinho também o configurava.

Como assim o configurava? Sim, era necessário informar vários dados que seriam necessários para ativação do serviço/produto contratado, como por exemplo, domínio, plataforma (Linux ou Windows) etc. Todo esse trabalho para o cliente nos causava um alto índice de abandono de compra.

Como podemos ver nessa imagem, além de alguns problemas de negócio, nós tínhamos várias dificuldades técnicas, como escalabilidade, resiliência, sistema totalmente monolítico. Tudo isso causava impacto na hora de dar manutenção e de criar novas funcionalidades no sistema.

Inicialmente, começamos a fazer uma análise, buscando entender nossa real necessidade, cases de soluções e de possíveis arquiteturas.

Uma arquitetura de software que tem ganhado muita atenção nos últimos anos é a de microsserviços. Ela é uma alternativa à arquitetura de aplicação monolítica e, basicamente, consiste em dividir uma aplicação grande em várias aplicações menores, com propósitos específicos.

Se você quer ler mais sobre o assunto, indico este artigo falando sobre quando utilizar microsserviços.

Após avaliarmos a situação, optamos por tentar migrar nosso sistema de vendas para a arquitetura de microsserviços. Falo em “tentar” porque quem trabalha ou já trabalhou com sistemas legados sabe que não é tão fácil e simples sair criando algo novo.

Arquitetura do novo carrinho de compras

Com o desenvolvimento da nova arquitetura, separamos as responsabilidades, deixando no carrinho de compras somente o necessário para o cliente conseguir adquirir aos serviços. Assim, ficou para outra etapa a configuração do produto. Com isso já diminuímos duas etapas do processo de compras antigo.

Distribuindo as responsabilidades, nós temos hoje a seguinte arquitetura, com aplicações isoladas em containers Docker: uma API recebe os dados do pedido e envia para uma fila, essa fila envia para uma outra aplicação que, então, processa o pedido.

Visão geral da arquitetura atual

Na imagem acima, temos uma visão geral das diversas aplicações presentes na nossa arquitetura e como elas se comunicam.

  • Cart-Admin: Sistema interno para gestão de produtos, combos e pedidos;
  • Site e Cart-Client: Interface do carrinho de compras;
  • Cart-Painel: Interface do carrinho de compras dentro do painel de controle;
  • API Oauth: API de autenticação de aplicações clients e usuários internos;
  • DB Master: Banco de dados legado, onde pedidos são inseridos;
  • DB Slave: Réplica do DB Master, para consultas necessárias na API do Cart, assim a API Cart não tem dependência do banco de dados legado;
  • Cart-Server: API, fila e o consumer.

Abaixo temos uma visão mais detalhada sobre as aplicações que recebem, enviam para a fila e processam o pedido.

Aplicações independentes

Optamos por ter uma fila utilizando o RabbitMQ para termos total controle e independência dos sistemas legado. Se, por algum motivo, o consumer não conseguir inserir o pedido, a fila consegue gerenciar isso, fazendo novas tentativas ou até armazenando em uma fila de erros.

Com esta arquitetura, temos a possibilidade de escalar facilmente cada aplicação ou banco de dados, conforme a necessidade. Também podemos adicionar o carrinho onde for necessário, fazendo somente a integração com a API.

Monitoramento/ Logs

Uma arquitetura de microsserviços distribuído é muito mais difícil de monitorar, mas é imprescindível, para isso não poupamos na monitoria e logs.

Para monitorar as aplicações e a comunicação entre elas, utilizamos a stack open source da Elastic.

Com os Bets, conseguimos capturar as informações que necessitamos, como informações de arquivos de logs e requisições HTTP. Através do Logstash enviamos para armazenar no Elasticsearch somente as informações que achamos cruciais para identificar possíveis problemas, e no Kibana criamos nossos dashboard para visualizar esses dados.

Como nosso desenvolvimento, hoje, dentro da KingHost, é basicamente utilizando a linguagem PHP, nós também utilizamos o Monolog para armazenar os logs e nos notificar se acontecer qualquer problema.

Com o Monolog, nós categorizamos e identificamos a gravidade de uma exceção, por exemplo, e notificamos a equipe por e-mail ou chat, dependendo da gravidade.

Outra stack que utilizamos para nos auxiliar no monitoramento foi o Prometheus, Grafana, AlertManager, NodeExporter e cAdvisor.

Com esta stack, nós conseguimos monitorar o servidor e os containers Docker, capturar estas métricas, enviar alertas e criar dashboards no grafana.

Para quem quiser saber mais sobre essa stack e como utilizá-la, pode ler o artigo monitorando aplicações PHP com Prometheus.

Principais tecnologias utilizadas

Como comentei anteriormente, a principal linguagem utilizada no desenvolvimento de aplicações na KingHost é o PHP. Neste projeto, nós utilizamos alguns frameworks, como Lumen que é um micro-framework do Laravel, além do micro-framework Slim.

Além do próprio PHP, utilizamos também seus frameworks e as stacks para logs, ferramentas como RabbitMQ para gerenciamento da fila de pedidos, GitLab como repositório de código fonte, Jenkins para build e deploy, e Portainer para gerenciar de forma gráfica os containers Docker.

Melhorias e considerações finais

Como comentei no início do artigo, este projeto foi um dos nossos primeiros utilizando este tipo de arquitetura dentro da KingHost, então, temos muito a melhorar e refinar; por exemplo, ainda precisamos trabalhar em melhorias para o monitoramento e os alertas.

Falando um pouco de resultados e benefícios, já estamos vendo vários impactos desde a implementação do projeto que começou em fevereiro deste ano. Tanto voltado para questões do negócio como para questões técnicas, é possível relatar alguns resultados.

Por exemplo, diminuímos o tempo para o cliente completar a compra, baixamos o índice de abandono e vendas perdidas,  aumentamos a taxa de conversão, como consequência aumentando a porcentagem de compras concluídas em até 60%. E como resultados técnicos, fomos beneficiados com algumas facilidades, como deploys separados, melhor manutenção, ganho de escalabilidade e flexibilidade.

Essa arquitetura, onde temos um grande sistema quebrado em serviços menores e mais leves, por critério de funcionalidades de negócio, integrados via HTTP (ou alguma arquitetura de mensageira) é o que forma a famosa arquitetura de microsserviços. Evidentemente, existem outros casos de arquiteturas de microsserviços que podem usar diferentes tecnologias, bancos de dados compartilhados entre serviços, serviços que se comunicam com outros serviços e assim por diante.

Faz parte do papel do arquiteto de software tomar decisões baseadas em trade-offs. Nunca teremos uma solução perfeita. Sempre precisamos escolher entre vantagens e desvantagens, como foi o nosso caso com a utilização de microsserviços. O importante é analisar calmamente qual é a melhor abordagem para cada situação.

Fique atento, pois no evento Conexão KingHost, evento online e gratuito que acontecerá em setembro, vamos debater microsserviços e outros assuntos interessantes sobre tecnologia e inovação. E você? Já trabalhou em algum projeto com arquitetura de microsserviços? O que achou? Deixe seu comentário!