RabbitMQ & AMQP – #2 – Pra que Mensageria?
Publicado em: quarta-feira, 20 de fev de 2019
Categorias: RabbitMQ de A a Z
Tags: AMQP | RabbitMQ

Embora fosse a hora de falar do standard, acho que é preciso definir mensageria antes. Vamos aos principais pontos.

Mensageria

É pra mim?

Talvez você já tenha se perguntado a respeito do sentido de usar uma solução de filas, mensageria, enfim um message broker como RabbitMQ. Será que faz algum sentido? Ou esse pessoal deve morrer de fome1, por que na prática uma boa query otimizada, em um banco de dados, e algumas threads dão conta do recado?

Na prática depende. Se você não tem um servidor de banco de dados que tenha custado dezenas milhares de reais, se não tem processamento de queries que levem horas ou até dias: Então muito provavelmente você não tem um problema… por enquanto. Isso quer dizer que seu workload é baixo o suficiente e tudo funciona aparentemente normal. Muitas empresas são pequenas o suficiente para conviverem com essa estratégia.

E quando a demanda cresce?

Essa estratégia de pooling (queries periódicas produzindo massa para processamento) não está categoricamente errada quando sua demanda é baixa. O problema ocorre quando sua empresa cresce, sua demanda cresce, e torcemos para isso aconteça!

Quando a demanda cresce, você começa a encontrar os limitadores da abordagem, que inicialmente são sanados com escala vertical, até que alcançamos o limite do viável financeiramente e então optamos por reescrever uma parte de nossas aplicações, afim de viabilizar escala horizontal, que por sua vez é mais barata.

De fato é muito comum encontrarmos empresas que operem dessa forma. Principalmente nos sistemas contábeis com períodos de fechamento contábil, seja ele anual, mensal ou quinzenal.

Esse é um cenário típico em que entre um ciclo de processamento e outro, nada (ou quase nada) acontece com boa parte dos dados.

É análogo a uma fábrica, como se uma esteira de produção simplesmente parasse (ou quase) 25 dias do mês, mas nos 5 dias de fechamento do mês, essa esteira tivesse de trabalhar pelo mês todo.

Claro que fechamento contábil não é o melhor exemplo, já que há um fator disruptivo nessa equação. Mas tenho mais exemplos.

Você tem um problema!

O problema dessa abordagem é que, em linhas gerais para atender uma grande carga de trabalho em uma janela de tempo muito curta, você precisará de equipamento mais e melhor hardware, diferente de quem consegue distribuir a mesma carga de trabalho com paralelismo ou simplesmente processando interruptamente. Em alguns casos, essa auto-produção de picos de processamento pode ser considerada até auto-sabotagem.

Quando interrompemos um processamento por muito tempo, ao retomá-lo, nos deparamos com grandes cargas de trabalho, pois as atividades foram acumuladas durante o período de inatividade. E na prática estamos produzindo picos de processamento (desnecessários). Esse pico não foi produzido pelo aumento da quantidade de vendas, ou um aumento repentino no consumo de seus serviços. Foi produzido pelo simples acúmulo de processamento pendente, ocasionado pela ociosidade de processamento. O que produziu tal fenômeno, nesses casos, é uma decisão técnica ou estratégica, uma decisão ruim.

Até em Ecommerces relevantes, já vi o processo de integração de pedidos ser baseado em uma query, que pega todos os pedidos que haviam tido pagamento processado com sucesso e encaminhando para a expedição, simplesmente com uma mera troca de estado em uma coluna específica do banco. Será que isso é realmente eficiente? Por sorte eles não fazem mais isso.

Boa parte das demandas por hardware são oriundas de decisões como essa. Com a produção interna de picos de processamento, somente com máquinas muito potentes é possível escalar, é a escala vertical, onde empenhamos mais capacidade de processamento, mais memória, mais disco, em um mesmo hardware.

Nós sabemos esses recursos são escassos e limitados, portanto é muito mais barato escalar horizontalmente pois o custo hardware mediano ou bom e infinitamente menor do que o curso de hardware ótimo.

Escalar verticalmente custa caro. Afinal, você consegue comprar até 12 computadores com processadores I3 e 4GB de RAM, mas dificilmente conseguirá pagar o mesmo valor por uma máquina de 48GB de RAM e um Xeon de última geração.  Algumas decisões erradas fazem você ter de tomar essas decisões.

Analogia – Lavanderia

Eu não sei se ainda se usa o conceito de “muda de roupa”, que representa um conjunto completo de vestimenta, independente do tipo, é tudo que você vestindo agora é uma muda de roupa.

Imagine que você produz 2 mudas de roupa suja para lavar todos os dias, ao longo de uma semana são 14 mudas. Agora imagine que são 2 pessoas produzindo isso. Em 7 dias são 28 mudas de roupa. Se você deixar para lavar sua roupa no final de semana, e quer garantir que tudo seja lavado e posteriormente fique seco a tempo para a próxima semana, precisará de uma máquina com capacidade de processamento muito maior, e demandará um espaço para alojar a roupa que precisa secar, também muito maior. Afinal, levando em conta que uma muda de roupa tem pelo menos uma short/calça/caia, uma camisa e uma roupa íntima, são pelo menos 84 peças de roupa para lavar no final de semana.

Sem acumulo, você precisa de uma máquina menor, e menos espaço. A dinâmica de processamento contínuo é exatamente essa.

3 milhões de pedidos por dia

Vamos pegar o exemplo da GO-JEK, empresa da Indonesia, ela apresenta um cenário de 3 milhões de orders por dia no post From 5,000 Orders to 3M Orders Per Day.

Embora não tenhamos informações sobre picos, vamos distribuir por 24 horas, como se esse workload fosse linear, distribuído de forma igualitária durante todo o dia, vamos abordar um desses dias em que foram realizados 3 milhões de pedidos.

Assim temos:

  • 3 000 000 pedidos no dia
  • Que se reflete em 125 000 pedidos por hora
  • 2084 pedidos por minuto,
  • e 35 pedidos por segundo

Embora 3 milhões de pedidos possa parecer muito, 35 pedidos or segundo, já deixa de parecer um número tão inalcançável, né?

E quais são os problemas de realizar 1 query por segundo em uma base assim? Concorrência, latência, demanda por otimização, dead locks….

Para atender a 1 query por segundo, você precisará gastar muito processamento e em algum momento não será suficiente.

Escala

Pelo ponto de vista de mensageria, teu pedido nunca pára. Por maior que seja o fluxo, ele sempre está em uma fila, aguardando a disponibilidade de um worker para processá-lo. Sua carga de trabalho está sempre distribuídas entre diversos workers. Quando algum cai, sua outro passa a atender aquela demanda. E pela ótica de mensageria, você não tem esforço adicional para fazer isso.

Embora esteja implícito, isso se reflete em resiliência.

Principais capacidades

Cada mensagem processada (e que não sofreu falhas no seu ciclo de vida) é processada somente por 1 worker, independente de termos 1 ou 1000 workers consumindo essa fila. Essa é uma característica imutável do AMQP. Além disso, com a tolerância a falhas (dada pelo acknowledge, comando que afirma que a mensagem foi processada e pode ser excluída), caso um processo falhe durante o processamento de uma mensagem ou um um cluster inteiro morra, as mensagens sem acknowledge podem:

  • voltar para a fila para serem processadas por outro cluster ou aguardarem o cluster se recuperar.
  • serem enviadas para uma fila especial (de erro)

Ambas as opções são válidas e são decisões de projeto que se aplicam nas configurações no RabbitMQ.

Mas porque “que não sofreu falhas no seu ciclo de vida”. Veremos nos próximos posts que há políticas para retry no RabbitMQ. A mensagem pode morrer, quando ocorre uma falha, mas também pode voltar para a fila, ou ainda ser enviada para uma fila especial. Tudo isso é configurável, mas vamos ver isso mais à frente.

Comparando

O hardware necessário para atender 35 pedidos por segundo é muito menor do que um hardware que precise atender 3 milhões de pedidos em uma janela de tempo pequena. E vamos sentir os custos no servidor de banco de dados, no application server e no disco/storage e memória. Enfim, os desafios para trabalhar com grandes volumes podem ser reduzidos ao trabalharmos com porções menores, em uma granularidade que ajuda a otimizar todo o processo, deixamos de tentar processar grandes massas, para processar interruptamente um pouquinho, item-a-item, como formigas.

AMQP e RabbitMQ ajudam nessa jornada. Mas também não podemos nos esquecer do Azure Service Bus, que também é uma implementação AMQP.

Conclusão

Graças à adição da estratégia de mensageria a um cenário assim, temos uma capacidade muito maior de processamento a um custo muito menor. Na prática conseguimos atender a grandes cargas de trabalho com um menor custo.

Ao olharmos com mais profundidade para AMQP e RabbitMQ nos próximos posts, veremos que na prática são compostos por poucos e simples conceitos e implementações, no entanto como lego, podem compor soluções das mais variadas.

Lembra que eu disse que uma mensagem só pode ser processada por um worker, e nunca será processada pelo segundo worker, na mesma fila? Bom, se você quer que 2 workers processem a mesma mensagem, você precisa de 2 filas… orabolas! Isso vai ficar claro no decorrer da série.

Enfim no próximo, temos as definições!

Obs:

1 | Provocação: Esse pessoal deve morrer de fome por não ser algo de fato usado pelo mercado.

Luiz Carlos Faria

Mensagem do Autor

Espero que goste desse post. Não deixe de comentar e falar o que achou. 

Se acha que esse post pode ajudar alguém que você conheça, compartilhe!

 

Eventos passados

agosto 2020
julho 2020
Nenhum evento encontrado!
Carregar Mais

Publicidade

Assine

6 Comentários

  1. Roberto Ramos

    Luiz,

    Existe alguma forma de evitar publicação de mensagens repetidas, com alguma propriedade da mensagem?

    Responder
    • Luiz Carlos Faria

      Cada mensagem é única, o RabbitMQ não faz controle em relação a dados na mensagem. Ele não tem essa responsabilidade.
      Assim, não há muito o que fazer exceto produzir mensagens corretamente sem duplicidade.

      Responder
    • Luiz Carlos Faria

      Tem um monte de gambiarra que dá para fazer para evitar o processamento de mensagens idênticas, mas são gambiarras. Não aconselho. Me chama no chat no telegram, vamos conversar sobre isso.

      Responder
  2. Flávio Nunes

    Olá Luiz tudo bem?

    Queria tirar uma dúvida:
    Eu preciso processar uma (certa quantidade de dados, hoje aproximadamente 30 msg por segundo mas esse numero deve crescer) que chega em um banco de dados. Estou pensando em usar o RabbitMQ.
    O problema e que os dados vem de milhares de dispositivos e preciso fazer o processamento dos dados em paralelo por dispositivo.
    Criar uma fila para cada dispositivo seria uma forma adequada de fazer isso? ou existe uma maneira melhor de se fazer isso?

    Você poderia me dar uma sugestão ou indicação de algum material para me ajudar.

    Responder
    • Luiz Carlos Faria

      Flavio, dá sim para criar uma fila por dispositivo.
      Mas por experiência, em geral essa é uma solução “errada”.

      Para processar paralelamente você não precisa distribuir em várias filas, basta aumentar o número de consumidores.
      Uma fila já é escalável para suportar milhares e até milhões de consumidores.

      Como disse, “parece errado”, preciso entender melhor, e com mais profundidade para poder ser mais assertivo. Mas em linhas gerais é isso.

      Grande abraço e muito obrigado por perguntar!

      Responder
      • Flávio Nunes

        Opa Luiz. Primeiro muito obrigado pela sua resposta, ela vai me ajudar muito a não seguir por uma abordagem incorreta.

        Vou tentar te explicar o cenário, e qual seria minha principal dúvida.
        Tenho milhares de dispositivos conetando em um servidor TCP que recebe pacote de dados e guarda essas informações para processar assim que possível.

        Porem preciso seguir uma ordem de processamento por dispositivo. Por exemplo: Tenho os dispositivos A, B, C enviando informações continuamente para esse servidor. Eu posso processar A, B, C em paralelo e fora de ordem entre eles sem problemas.

        Mas eu não posso por exemplo processar o pacote numero 3 do dispositivo A sem que os pacotes 1 e 2 desse mesmo dispositivo já tenham sido processado.

        Eu sei que seu tiver uma única fila e um único consumidor eu não vou ter problemas com isso já que eles vão seguir a ordem da fila no padrao FIFO. Mas se eu tiver mais de um consumidor por exemplo existe alguma forma que me possibilite garantir essa ordem por dispositivo?

        Abraço e muito obrigado pela atenção!

        Responder

Enviar um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.

Lives

Fique de olho nas lives

Fique de olho nas lives no meu canal do Youtube, no Canal .NET e nos Grupos do Facebook e Instagram.

Aceleradores

Existem diversas formas de viabilizar o suporte ao teu projeto. Seja com os treinamentos, consultoria, mentorias em grupo.

Agenda & Eventos

agosto

setembro 2020

outubro
DOM
SEG
TER
QUA
QUI
SEX
SAB
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3
Eventos para setembro

1st

Sem Eventos
Eventos para setembro

2nd

Sem Eventos
Eventos para setembro

3rd

Sem Eventos
Eventos para setembro

4th

Sem Eventos
Eventos para setembro

5th

Sem Eventos
Eventos para setembro

6th

Sem Eventos
Eventos para setembro

7th

Sem Eventos
Eventos para setembro

8th

Sem Eventos
Eventos para setembro

9th

Sem Eventos
Eventos para setembro

10th

Sem Eventos
Eventos para setembro

11th

Sem Eventos
Eventos para setembro

12th

Sem Eventos
Eventos para setembro

13th

Sem Eventos
Eventos para setembro

14th

Sem Eventos
Eventos para setembro

15th

Sem Eventos
Eventos para setembro

16th

Sem Eventos
Eventos para setembro

17th

Sem Eventos
Eventos para setembro

18th

Sem Eventos
Eventos para setembro

19th

Sem Eventos
Eventos para setembro

20th

Sem Eventos
Eventos para setembro

21st

Sem Eventos
Eventos para setembro

22nd

Sem Eventos
Eventos para setembro

23rd

Sem Eventos
Eventos para setembro

24th

Sem Eventos
Eventos para setembro

25th

Sem Eventos
Eventos para setembro

26th

Sem Eventos
Eventos para setembro

27th

Sem Eventos
Eventos para setembro

28th

Sem Eventos
Eventos para setembro

29th

Sem Eventos
Eventos para setembro

30th

Sem Eventos
Share This