Páginas filhas
  • DTTALK1-270 Estudar forma de otimizar uso do RabbitMQ na cloud TOTVS

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

Introdução

Este documento descreve os resultados obtidos durante o estudo para avaliar a performance do RabbitMQ em um ambiente cloud. O objetivo do estudo era determinar os limites do RabbitMQ em um ambiente clusterizado e em nuvem, para definir, entre outras coisas, a forma de instalação e uso do RabbitMQ em tal cenário.

Desenvolvimento

Os testes foram realizados tendo como premissa tentar simular um cenário o mais próximo possível de uma situação real.

O ambiente de execução dos testes foi disponibilizado com as seguintes características:

  • Cluster Kubernetes  composto de 2 nós, configurado no provedor de nuvem Microsoft Azure.
  • Cada nó disponibilizou 16 Gb de RAM e 4 CPUs, mas os pods foram limitados inicialmente a 2 Gb e 1 CPU cada.
  • RabbitMQ instalado em modo cluster de alta disponibilidade (HA), composto de 2 instâncias, uma em cada nó. 
  • Instalação com vhost padrão apenasinicialmente.

Para gerar carga a ser manipulada pelo RabbitMQ e assim poder avaliar seu desempenho, foi utilizada a ferramenta de teste de carga perf-test, disponibilizada pela Pivotal, desenvolvedora do RabbitMQ. 

A ferramenta pode ser obtida no GitHub, como código fonte ou em formato binário. É desenvolvida em Java e permite avaliar um amplo número de situações através de parâmetros fornecidos por linha de comando ou como variáveis de ambiente, o que é interessante para uso em contêineres como o Docker.

Inclusive, está foi a abordagem adotada. Gerou-se uma imagem Docker contendo o programa de teste em formato binário. A imagem foi disponibilizada no repositório docker.totvs.io, com a tag rabbitmq/carga:latest.

Informações
Para baixar a imagem, é necessário ter acesso autorizado ao repositório, sendo que o mesmo é exclusivo para colaboradores da TOTVS.

Parâmetros de testes

Abaixo estão listados os parâmetros da ferramenta perf-test utilizados para realização dos testes de carga. Os parâmetros foram configurados como variáveis de ambiente nos arquivos de deployment das imagens do programa de teste.

  • CONSUMERS: Quantidade de consumidores de mensagens a serem iniciados pela instância.
  • PRODUCERS: Quantidade de produtores de mensagens a serem iniciados pela instância.
  • QUEUE_PATTERN: Expressão que define o padrão de nome das filas a serem criadas pelo programa de teste.
  • QUEUE_PATTERN_FROM: Valor inicial para identificação da fila, que será usado na expressão definida no parâmetro QUEUE_PATTERN.
  • QUEUE_PATTERN_TO: Valor final para identificar a fila, que será usado na expressão do parâmetro QUEUE_PATTERN.
  • QUEUE_ARGS: Propriedades adicionais das filas.
  • QOS: Quantidade de mensagens que cada consumidor obterá da fila a cada vez que for buscar mais mensagens.
  • SIZE: Tamanho da mensagem, em bytes.
  • URI: Endereço do broker, no formato amqp://[<usuario>:<senha>@]<IP_nome_servidor>:<porta_serviço_amqp>[/<vhost>]
  • VARIABLE_RATE: Determina a taxa de produção de mensagens num intervalo de tempo, no formato <qtde_msg/segundo>:<segundos>. Para informar taxas variadas, deve-se utilizar "," para separar os valores. 
    • Exemplo: 200:30,1000:120,40:10. 
    • Serão geradas 200 mensagens por segundo durante 30 segundos; em seguida, 1000 msgs/seg durante 120 segundos e então, 40 msgs/seg. durante 10 segundos. Ao final, retorna-se a taxa inicial (200 msgs/seg em 30 segs), repetindo os demais valores indefinidamente, ou até o tempo máximo estipulado.
  • VARIABLE_SIZE: Determina a variação de tamanho da mensagem num intervalo de tempo, no formato <qtde_bytes>:<segundos>. Segue a mesma lógica do parâmetro VARIABLE_RATE.

Os valores de alguns parâmetros permaneceram fixos ao longo dos testes e estão descritos a seguir. Os valores que se modificaram conforme necessidade serão descritos nos cenários de teste correspondentes.

  • CONSUMERS: 10
  • PRODUCERS: 10
  • QUEUE_PATTERN: "perf-test-%02d"
  • SIZE: 3000

Conforme os valores acima, cada instância da imagem do programa de teste iniciará 10 threads para produção/consumo de mensagens (conforme o perfil), com as filas sendo nomeadas como perf-test-01, perf-test-02, e assim por diante. As mensagens produzidas, quando não for especificada variação de tamanho ao longo do tempo (VARIABLE_SIZE), serão de 3000 bytes.

Arquitetura do ambiente de teste

O diagrama a seguir mostra como os elementos de software foram organizados no cluster Kubernetes para a realização dos testes:

draw.io Diagram
bordertrue
viewerToolbartrue
fitWindowfalse
diagramNameArquitetura de teste
simpleViewerfalse
width600
diagramWidth979
revision2

Na representação acima, cada produtor (producer) e cada consumidor (consumer) representa um deployment, com parametrizações específicas para filas a criar. Por isso, cada um possui identificador específico, variando de 1 a 5. Entretanto, todas as instâncias foram geradas a partir da mesma imagem Docker relativa ao programa de testes.

Abaixo um exemplo de deployment do Kubernetes demonstrando as configurações relativas ao producer-1 para o último cenário de teste executado.


Bloco de código
languageyml
titleDeployment do producer-1
collapsetrue
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: producer-1
  namespace: producers
  labels:
    app: producer-1
spec:
  replicas: 0
  selector:
    matchLabels:
      app: producer-1
  template:
    metadata:
      labels:
        app: producer-1
    spec:
      containers:
        - name: producers
          image: docker.totvs.io/rabbitmq/carga:latest
          imagePullPolicy: Always
          env:
            - name: PRODUCERS
              value: "10"
            - name: CONSUMERS
              value: "0"
            - name: QUEUE_PATTERN
              value: "perf-test-%02d"
            - name: QUEUE_PATTERN_FROM
              value: "1"
            - name: QUEUE_PATTERN_TO
              value: "10"
            - name: URI
              value: "amqp://admin:[email protected]:8081"
            # Varia o tamanhos das mensagens em um intervalo de tempo. Formato: <tamanho em bytes>:<segundos>
            - name: VARIABLE_SIZE
              value: "3000:60,1000:120,4000:60,500:300"
            # Varia a quantidade de mensagens em um intervalo de tempo. Formato: <qtde/segundo>:<segundos>
            - name: VARIABLE_RATE
              value: "30:60,100:120,300:60,50:300"
            # Máximo de mensagens em uma fila. 10000 é um limite que visa performance de entrega
            - name: QUEUE_ARGS
              value: "x-max-length=20000"


Conforme se pode verificar acima, cada instância de producer-1 iniciará 10 produtores (PRODUCERS), cada um associado a uma fila com nomes variando de "perf-test-01" a "perf-test-10" (QUEUE_PATTERN, QUEUE_PATTERN_FROM, QUEUE_PATTERN_TO).

O tamanho das mensagens variará da seguinte forma (VARIABLE_SIZE):

  1. 3000 bytes durante 60 segundos,
  2. 1000 bytes durante 120 segundos,
  3. 4000 bytes durante 60 segundos,
  4. 500 bytes a cada 5 minutos.

A taxa de produção de mensagens variará conforme segue (VARIABLE_RATE):

  1. 30 mensagens/segundo durante 60 segundos,
  2. 100 mensagens por segundo durante 120 segundos,
  3. 300 msgs/seg por 60 segundos,
  4. 50 msgs/seg durante 5 minutos.

As filas serão criadas para receber o máximo de 20000 mensagens (QUEUE_ARGS).

A seguir, o arquivo de deployment do consumer-5, para o último cenário de teste.

Bloco de código
languageyml
titleDeployment do consumer-5
collapsetrue
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: consumer-5
  namespace: consumers
  labels:
    app: consumer-5
spec:
  replicas: 0
  selector:
    matchLabels:
      app: consumer-5
  template:
    metadata:
      labels:
        app: consumer-5
    spec:
      containers:
        - name: consumers
          image: docker.totvs.io/rabbitmq/carga:latest
          imagePullPolicy: Always
          env:
            - name: PRODUCERS
              value: "0"
            - name: CONSUMERS
              value: "10"
            - name: QUEUE_PATTERN
              value: "perf-test-%02d"
            - name: QUEUE_PATTERN_FROM
              value: "41"
            - name: QUEUE_PATTERN_TO
              value: "50"
            - name: URI
              value: "amqp://admin:[email protected]:8081/app2"
            # Máximo de mensagens em uma fila. 10000 é um limite que visa performance de entrega
            - name: QUEUE_ARGS
              value: "x-max-length=20000"
            # Consumer prefetch count: quantidade de mensagens que o consumidor obterá da fila a cada vez.
            - name: QOS
              value: "500"


No arquivo acima, cada instância do consumer-5 iniciará 10 threads (CONSUMERS) para consumir das filas cujos nomes variarão de "perf-test-41" a "perf-test-50" (QUEUE_PATTERN, QUEUE_PATTERN_FROM, QUEUE_PATTERN_TO).

As filas serão criadas para conter o máximo de 20000 mensagens (QUEUE_ARGS) e os consumidores recuperaram 500 mensagens a cada vez. 

Cenários de teste

Os cenários a seguir apresentarão os parâmetros usados, procedimentos efetuados e as observações coletadas, de forma a evidenciar o desempenho do RabbitMQ no referido cenário.


Expandir
titleVersão 1

Este cenário foi criado para validar a infraestrutura (cluster, imagem Docker) e contemplou apenas um deployment de producer e um deployment de consumer.

Nó do clusterRabbitMQ
MemóriaCPUVhostsMemory Watermark
2 Gb1/800 Mb

Os parâmetros de deployment utilizados foram os seguintes:

DeploymentPRODUCERSCONSUMERSQUEUE_PATTERNQUEUE_PATTERN_FROMQUEUE_PATTERN_TOSIZE
Producer-1100perf-test-%02d1103000
Consumer-1010perf-test-%02d110n/a

A tabela abaixo demonstra o incremento de produtores e consumidores e resultados obtidos.

Instâncias Producer-1

Threads por fila

Instâncias Consumer-1

Threads por filaQtde. FilasConexões

Mensagens produzidas por segundo (média)

Mensagens consumidas por segundo (média)

Observações
11110

Prod: 10

Cons: 10

15001400Houve crescente acumulo de mensagens nas filas, devido a taxa de produção ser maior que a de consumo.
112110

Prod: 20

Cons: 10

13001300A quantidade de mensagens nas filas estabilizou. A taxa de consumo por thread diminuiu por conta da concorrência de 2 threads de consumo por fila.
113110

Prod: 30

Cons: 10

15001600Redução gradual de mensagens nas filas. Com 3 threads por fila, a taxa de consumo teve nova redução, mas ainda sim foi possível superar a taxa de produção e diminuir a quantidade de mensagens nas filas.

Considerações:

  • O programa de teste tentou mandar e consumir o máximo de mensagens por segundo, de forma que o consumo se mostrou mais lento do que a produção.
  • O equilíbrio da fila foi alcançado com a proporção de 2 threads consumidoras para cada produtora.
  • Caso não se iniciasse uma nova instância de consumer, as mensagens iriam se acumular na fila e em algum momento causariam estouro de memória no RabbitMQ.


Expandir
titleVersão 2

Cenário configurado para testar alta demanda de mensagens em múltiplas filas.

Nó do clusterRabbitMQ
MemóriaCPUVhostsMemory Watermark
2 Gb1/800 Mb

Os parâmetros de deployment utilizados foram os seguintes:

DeploymentPRODUCERSCONSUMERSQUEUE_PATTERNQUEUE_PATTERN_FROMQUEUE_PATTERN_TOSIZE
Producer-1100perf-test-%02d1103000
Producer-21120
Producer-32130
Producer-43140
Producer-54150
Consumer-1010perf-test-%02d110n/a
Consumer-21120
Consumer-32130
Consumer-43140
Consumer-54150

A tabela abaixo demonstra o incremento de produtores e consumidores e resultados obtidos.

Instâncias Producer

Threads por fila

Instâncias Consumer

Threads por filaQtde. FilasConexões

Mensagens produzidas por segundo (média)

Mensagens consumidas por segundo (média)

Observações
5 (1 por deployment)15 (1 por deployment)150 (10 por deployment)

Prod: 50

Cons: 50

90006000O broker sofreu sobrecarga de memória e os nós reiniciaram várias vezes.
1 (producer-1)11 (consumer-1)110 (producer-1)

Prod: 10

Cons: 10

30002700O broker estabilizou, com mensagens acumulando-se gradualmente nas filas.
2 (producer 1 e 2)11 (consumer-1)120 (producer-1 e 2)

Prod: 20

Cons: 10

30002700Os nós reiniciaram na tentativa de subir o producer-2. Foi atingido o limite de memória devido acumulo de mensagens nas filas do producer-2, já que não havia consumidor ativo para elas.
2 (producer-1 e 2)12 (consumer-1 e 2)120 (producer-1 e 2)

Prod: 20

Cons: 20

50004500Após reiniciar, os nós conseguiram acomodar os producers e consumers.
2 (producer 1 e 2)13 (consumer 1 a 3)130 (consumer 1 a 3)

Prod: 20

Cons: 30

50004500Lentidão no broker para criar as filas correspondentes ao consumer-3. A intenção seria subir o producer-3 após todas as filas estarem disponíveis no RabbitMQ.
2 (producer 1 e 2)15 (consumer 1 a 5)150 (consumer 1 a 5)

Prod: 20

Cons: 50

50004500Um dos nós reiniciou. O limite de memória (watermark) foi superado frequentemente. O broker ficou extremamente lento para responder a interface de gerenciamento (management UI), que estava solicitando refresh a cada 10 segundo.

Considerações:

  • Ficou evidente que o limite de memória de 800 Mb é muito baixo para o cenário.
  • Também ficou visível que iniciar mais produtores que consumidores, com uma alta taxa de produção de mensagens leva rapidamente ao atingimento do limite de memória.
  • A queda de um nó gerou sobrecarga no outro nó, o que levou a queda deste também.


Expandir
titleVersão 3

Cenário configurado para testar alta demanda de mensagens em múltiplas filas, com variação de tamanho e taxa de produção de mensagens:

Nó do clusterRabbitMQ
MemóriaCPUVhostsMemory Watermark
2 Gb1/800 Mb

Os parâmetros de deployment utilizados foram os seguintes:

DeploymentPRODUCERSCONSUMERSQUEUE_PATTERNQUEUE_PATTERN_FROMQUEUE_PATTERN_TOVARIABLE_SIZEVARIABLE_RATE
Producer-1100perf-test-%02d110

3000:60, 

1000:120, 

4000:60, 

500:300 

300:60, 

1000:120, 

3000:60, 

500:300 

Producer-21120
Producer-32130
Producer-43140
Producer-54150
Consumer-1010perf-test-%02d110n/an/a
Consumer-21120
Consumer-32130
Consumer-43140
Consumer-54150

A tabela abaixo demonstra o incremento de produtores e consumidores e resultados obtidos.

Instâncias Producer

Threads por fila

Instâncias Consumer

Threads por filaQtde. FilasConexões

Mensagens produzidas por segundo (média)

Mensagens consumidas por segundo (média)

Observações
1 (producer-1)11 (consumer-1)110

Prod: 10

Cons: 20

20002000A quantidade de mensagens nas filas se manteve baixa. A taxa de produção variável gerou uma restrição nos produtores, que agora devem seguir os valores parametrizados.
2 (producer 1 e 2)12 (consumer 1 e 2)120

Prod: 20

Cons: 20

40004000Broker estável com pouca quantidade de mensagens acumuladas nas filas.
5 (producer 1 a 5)15 (consumer 1 a 5)150

Prod: 50

Cons: 50

93008900

Houve queda dos nós do broker. Só foi possível subir todas as 5 instâncias producer após subir as 5 instâncias consumer.

Cada novo producer adicionado gerava pico de memória no broker, excedendo o watermark máximo (800 Mb).

Crescimento gradual das mensagens acumuladas na fila.

5 (producer 1 a 5)110 (2 x consumers 1 a 5)250

Prod: 50

Cons: 100

91009000

Alguns minutos depois de estabilizar o broker com os 5 producers e 10 consumers, as mensagens acumuladas nas filas param de crescer.

Havia cerca de 1 milhão de mensagens nas filas, com um consumo de memória em torno de 600 Mb em cada nó.

5 (producer 1 a 5)115 (3 x consumers 1 a 5)350

Prod: 50

Cons: 150

91009800Redução gradual das mensagens acumuladas nas filas.

Considerações:

  • Mesmo com certa restrição na taxa de produção das mensagens, houve problemas com acumulo de mensagens na fila e consequente estouro de memória no broker.
  • As configurações de memória e CPU não estão sendo suficientes para a taxa de produção de mensagens em torno de 9 mil por segundo.


Expandir
titleVersão 4

Cenário configurado para testar demanda reduzida de mensagens (1/10 dos valores do cenário anterior) em múltiplas filas, com variação de tamanho e taxa de produção de mensagens:

Nó do clusterRabbitMQ
MemóriaCPUVhostsMemory Watermark
2 Gb1/800 Mb

Os parâmetros de deployment utilizados foram os seguintes:

DeploymentPRODUCERSCONSUMERSQUEUE_PATTERNQUEUE_PATTERN_FROMQUEUE_PATTERN_TOVARIABLE_SIZEVARIABLE_RATE
Producer-1100perf-test-%02d110

3000:60, 

1000:120, 

4000:60, 

500:300 

30:60, 

100:120, 

300:60, 

50:300 

Producer-21120
Producer-32130
Producer-43140
Producer-54150
Consumer-1010perf-test-%02d110n/an/a
Consumer-21120
Consumer-32130
Consumer-43140
Consumer-54150

A tabela abaixo demonstra o incremento de produtores e consumidores e resultados obtidos.

Instâncias Producer

Threads por fila

Instâncias Consumer

Threads por filaQtde. FilasConexões

Mensagens produzidas por segundo (média)

Mensagens consumidas por segundo (média)

Observações
5 (producer-1 a 5)15 (consumer-1 a 5)150

Prod: 50

Cons: 50

25002400

Com taxa menor na produção de mensagens, as instâncias dos produtores criaram as filas mais rápido que nos cenários anteriores. Os consumidores também conectaram mais rápido.

Ocorreu acumulo de mensagens nas filas, mas em velocidade menor que nos cenários anteriores, devido a redução da taxa.

Ao longo de uma noite inteira de funcionamento, devido o acumulo de mensagens, os nós reiniciaram cerca de 4 vezes cada.

5 (producer 1 a 5)110 (2 x consumer 1 a 5)250

Prod: 50

Cons: 100

25003500

Houve um ligeiro aumento da quantidade de mensagens na fila assim que as 5 novas instâncias de consumidores foi iniciada. Parece que o broker reduziu a entrega para gerenciar as novas conexões.

A performance geral do consumo não dobrou por conta da concorrência de consumidores nas filas (2 consumidores por fila).

Constatou-se lentidão na utilização do Management UI, parametrizado para fazer refresh a cada 10 segundos.

Considerações:

  • A redução na taxa de produção contribuiu para aumentar a estabilidade do broker, que reiniciou menos vezes do que nos cenários anteriores.
  • Para evitar completamente o risco de ter o broker reiniciando por excesso de memória, uma possibilidade é reduzir ainda mais a taxa de produção de mensagens, já que se aumentarmos o número de consumidores, podemos ter mais memória alocada por conta das novas conexões.


Expandir
titleVersão 5

Cenário configurado para testar o uso de múltiplos vhosts, mantendo-se a demanda reduzida de mensagens (1/10 dos valores do cenário anterior) em múltiplas filas, com variação de tamanho e taxa de produção de mensagens:

Nó do clusterRabbitMQ
MemóriaCPUVhostsMemory Watermark
2 Gb1/, app1, app2800 Mb

Os parâmetros de deployment utilizados foram os seguintes:

DeploymentVhostPRODUCERSCONSUMERSQUEUE_PATTERNQUEUE_PATTERN_FROMQUEUE_PATTERN_TOVARIABLE_SIZEVARIABLE_RATE
Producer-1/100perf-test-%02d110

3000:60, 

1000:120, 

4000:60, 

500:300 

30:60, 

100:120, 

300:60, 

50:300 

Producer-2app11120
Producer-32130
Producer-4app23140
Producer-54150
Consumer-1/010perf-test-%02d110n/an/a
Consumer-2app11120
Consumer-32130
Consumer-4app23140
Consumer-54150

A tabela abaixo demonstra o incremento de produtores e consumidores e resultados obtidos.

Instâncias Producer

Threads por fila

Instâncias Consumer

Threads por filaQtde. FilasConexões

Mensagens produzidas por segundo (média)

Mensagens consumidas por segundo (média)

Observações
5 (producer-1 a 5)15 (consumer-1 a 5)150

Prod: 50

Cons: 50

25002400

Houve queda dos brokers devido acúmulo de mensagens nas filas.

5 (producer 1 a 5)110 (2 x consumer 1 a 5)250

Prod: 50

Cons: 100

25003500

A performance geral do consumo não dobrou por conta da concorrência de consumidores nas filas (2 consumidores por fila).

Constatou-se lentidão na utilização do Management UI, parametrizado para fazer refresh a cada 10 segundos.

Considerações:

  • A separação em vhosts não teve impacto na estabilidade ou na performance do broker. Praticamente os mesmos resultados do cenário anterior foram observados neste.


Expandir
titleVersão 6

Cenário idêntico ao anterior, mas com aumento de memória e CPU nos nós (ver a seguir os novos valores):

Nó do clusterRabbitMQ
MemóriaCPUVhostsMemory Watermark
4 Gb2/, app1, app21,5 Gb

Os parâmetros de deployment utilizados foram os seguintes:

DeploymentVhostPRODUCERSCONSUMERSQUEUE_PATTERNQUEUE_PATTERN_FROMQUEUE_PATTERN_TOVARIABLE_SIZEVARIABLE_RATE
Producer-1/100perf-test-%02d110

3000:60, 

1000:120, 

4000:60, 

500:300 

30:60, 

100:120, 

300:60, 

50:300 

Producer-2app11120
Producer-32130
Producer-4app23140
Producer-54150
Consumer-1/010perf-test-%02d110n/an/a
Consumer-2app11120
Consumer-32130
Consumer-4app23140
Consumer-54150

A tabela abaixo demonstra o incremento de produtores e consumidores e resultados obtidos.

Instâncias Producer

Threads por fila

Instâncias Consumer

Threads por filaQtde. FilasConexões

Mensagens produzidas por segundo (média)

Mensagens consumidas por segundo (média)

Observações
5 (producer-1 a 5)15 (consumer-1 a 5)150

Prod: 50

Cons: 50

25002400

Houve queda dos brokers devido acúmulo de mensagens nas filas.

5 (producer 1 a 5)110 (2 x consumer 1 a 5)250

Prod: 50

Cons: 100

25003500

Ainda houve queda dos brokers, porem os níveis de consumo de memória ficaram abaixo do watermark máximo.

Percebeu-se uma performance extremamente baixa do Management UI.

Considerações:

  • Apesar do aumento de memória e CPUs ainda houve queda dos brokers mesmo com mais consumers que producers. A hipótese levantada é que o gerenciamento da saúde do nó pelo Kubernetes esteja derrubando-o quando ele deixa de responder no tempo definido. Devido a baixa performance, o RabbitMQ não está respondendo a tempo as requisições de healthcheck do Kubernetes.


Expandir
titleVersão 7

Cenário idêntico ao anterior, com ajuste das configurações do deployment do RabbitMQ no Kubernetes. O ajuste consistiu em alterar o período de verificação da saúde do nó de 10 segundos para 30 segundos, e o tempo para timeout foi ampliado de 5 segundos para 10 segundos:

Nó do clusterRabbitMQ
MemóriaCPUVhostsMemory Watermark
4 Gb2/, app1, app21,5 Gb

Os parâmetros de deployment utilizados foram os seguintes:

DeploymentVhostPRODUCERSCONSUMERSQUEUE_PATTERNQUEUE_PATTERN_FROMQUEUE_PATTERN_TOVARIABLE_SIZEVARIABLE_RATE
Producer-1/100perf-test-%02d110

3000:60, 

1000:120, 

4000:60, 

500:300 

30:60, 

100:120, 

300:60, 

50:300 

Producer-2app11120
Producer-32130
Producer-4app23140
Producer-54150
Consumer-1/010perf-test-%02d110n/an/a
Consumer-2app11120
Consumer-32130
Consumer-4app23140
Consumer-54150

A tabela abaixo demonstra o incremento de produtores e consumidores e resultados obtidos.

Instâncias Producer

Threads por fila

Instâncias Consumer

Threads por filaQtde. FilasConexões

Mensagens produzidas por segundo (média)

Mensagens consumidas por segundo (média)

Observações
5 (producer-1 a 5)15 (consumer-1 a 5)150

Prod: 50

Cons: 50

25002500

Não houve mais registro de queda dos nós.

A quantidade de mensagens nas filas ficou estável e num patamar bem baixo, em torno de 100 mensagens.

O refresh automático do Management UI foi desabilitado.

Considerações:

  • Aparentemente, o refresh automático do Management UI estava afetando a performance do broker. O desligamento do refresh automático, juntamente com os novos valores de healthcheck do nó pelo Kubernetes contribuíram para eliminar as quedas dos nós.


Expandir
titleVersão 8

Cenário baseado no anterior, com definição da quantidade máxima de mensagens em cada fila (x-max-length) em 10 mil mensagens. Neste cenário, será avaliado o comportamento do RabbitMQ quanto ao acumulo de mensagens quando as filas possuem tamanho máximo.

Informações
titleDeclaração de filas no RabbitMQ

A declaração de uma fila deve ser consistente entre os consumers e producers. No caso de propriedades como x-max-length, elas devem ser informadas tanto no deployment dos consumers quanto no dos producers, do contrário o RabbitMQ rejeita a declaração da fila e aborta a conexão.

Nó do clusterRabbitMQ
MemóriaCPUVhostsMemory Watermark
4 Gb2/, app1, app21,5 Gb

Os parâmetros de deployment utilizados foram os seguintes:

DeploymentVhostPRODUCERSCONSUMERSQUEUE_ARGSQUEUE_PATTERNQUEUE_PATTERN_FROMQUEUE_PATTERN_TOVARIABLE_SIZEVARIABLE_RATE
Producer-1/100x-max-kength=10000perf-test-%02d110

3000:60, 

1000:120, 

4000:60, 

500:300 

30:60, 

100:120, 

300:60, 

50:300 

Producer-2app11120
Producer-32130
Producer-4app23140
Producer-54150
Consumer-1/010x-max-length=10000perf-test-%02d110n/an/a
Consumer-2app11120
Consumer-32130
Consumer-4app23140
Consumer-54150

A tabela abaixo demonstra o incremento de produtores e consumidores e resultados obtidos.

Instâncias Producer

Threads por fila

Instâncias Consumer

Threads por filaQtde. FilasConexões

Mensagens produzidas por segundo (média)

Mensagens consumidas por segundo (média)

Observações
5 (producer-1 a 5)1Nenhuma050

Prod: 50

Cons: 0

42000

As mensagens enfileiradas rapidamente atingiram o limite de 500 mil mensagens (50 filas x 10 mil mensagens), ficando estável neste patamar.

Apesar disso, os produtores continuaram enviando mensagens, o que indica que as mensagens estavam sendo descartadas.

O limite de memória chegou ao máximo (1,5 Gb) e um dos nós reiniciou.

5 (producer 1 a 5)15 (consumers 1 a 5)150

Prod: 50

Cons: 50

42003700

A quantidade de mensagens enfileiradas baixou um pouco,  mantendo-se em 243 mil mensagens. O consumo de memória ficou próximo do limite de 1,5 Gb.

Lentidão na resposta do Management UI (em torno de 2 minutos para atualizar a página).

5 (producers 1 a 5)110 (2 x consumer 1 a 5)250

Prod: 50

Cons: 100

21002700

Com mais consumers que producers, as mensagens enfileiradas baixaram para 62 mil, aproximadamente.

Consequentemente, a memória dos nós também reduziu.

10 (2 x producer 1 a 5)210 (2 x consumer 1 a 5)250

Prod: 100

Cons: 100

43003700

Mensagens acumuladas voltaram a crescer.

Lentidão extrema do Management UI.

Considerações:

  • O cenário demonstra que é interessante limitar o tamanho das filas para dar mais estabilidade ao broker.
  • Para evitar perda de mensagens, é imprescindível manter as filas o mais curtas possível.


Expandir
titleVersão 9

Cenário baseado no anterior, com definição da quantidade de mensagens obtidas por cada consumidor (prefetch count).

Nó do clusterRabbitMQ
MemóriaCPUVhostsMemory Watermark
4 Gb2/, app1, app21,5 Gb

Os parâmetros de deployment utilizados foram os seguintes:

DeploymentVhostPRODUCERSCONSUMERSQUEUE_ARGSQUEUE_PATTERN

QUEUE_

PATTERN_

FROM

QUEUE_

PATTERN_

TO

QOSVARIABLE_SIZEVARIABLE_RATE
Producer-1/100x-max-kength=10000perf-test-%02d110n/a

3000:60, 

1000:120, 

4000:60, 

500:300 

30:60, 

100:120, 

300:60, 

50:300 

Producer-2app11120
Producer-32130
Producer-4app23140
Producer-54150
Consumer-1/010x-max-length=10000perf-test-%02d110200n/an/a
Consumer-2app11120
Consumer-32130
Consumer-4app23140
Consumer-54150

A tabela abaixo demonstra o incremento de produtores e consumidores e resultados obtidos.

Instâncias Producer

Threads por fila

Instâncias Consumer

Threads por filaQtde. FilasConexões

Mensagens produzidas por segundo (média)

Mensagens consumidas por segundo (média)

Observações
515150

Prod: 50

Cons: 50

45003200Broker estável, com mensagens enfileiradas atingindo o limite de 250 mil. Para evitar estouro de memória, mais consumers foram iniciados.
5110250

Prod: 50

Cons: 100

29502750Broker estável. Mensagens enfileiradas: 71 mil.
10210250

Prod: 100

Cons: 100

52004800Broker estável. Mensagens enfileiradas: 174 mil.
10215350

Prod: 100

Cons: 150

55004800Broker estável. Mensagens enfileiradas: 62 mil. A redução na performance do consumo pode estar ligada a concorrência de threads na mesma fila.
15315350

Prod: 150

Cons: 150

??Broker operacional, mas Management UI não responde mais às solicitações. Por este motivo as últimas medições não foram coletadas.

Considerações:

  • O uso de limite no tamanho das filas, associado ao prefetch dos consumidores gerou mais estabilidade no broker.
  • Até onde foi possível utilizar o Management UI, verificou-se que a memoria ficou abaixo do watermark de 1,5 Gb.
  • Os cenários até aqui apontam um limite máximo de 150 produtores e 150 consumidores para o broker operar com estabilidade, considerando as configurações de memória e CPU indicadas.
  • Será necessário pesquisar uma alternativa ao Management UI para realizar as medições dos próximos cenários.


Expandir
titleVersão 10

Cenário baseado no anterior, com ajuste da quantidade de mensagens obtidas por cada consumidor (prefetch count) e da quantidade máxima de mensagens nas filas (max length).

Nó do clusterRabbitMQ
MemóriaCPUVhostsMemory Watermark
4 Gb2/, app1, app21,5 Gb

Os parâmetros de deployment utilizados foram os seguintes:

DeploymentVhostPRODUCERSCONSUMERSQUEUE_ARGSQUEUE_PATTERN

QUEUE_

PATTERN_

FROM

QUEUE_

PATTERN_

TO

QOSVARIABLE_SIZEVARIABLE_RATE
Producer-1/100x-max-kength=20000perf-test-%02d110n/a

3000:60, 

1000:120, 

4000:60, 

500:300 

30:60, 

100:120, 

300:60, 

50:300 

Producer-2app11120
Producer-32130
Producer-4app23140
Producer-54150
Consumer-1/010x-max-length=20000perf-test-%02d110500n/an/a
Consumer-2app11120
Consumer-32130
Consumer-4app23140
Consumer-54150

A tabela abaixo demonstra o incremento de produtores e consumidores e resultados obtidos.

Instâncias Producer

Threads por fila

Instâncias Consumer

Threads por filaQtde. FilasConexões

Mensagens produzidas por segundo (média)

Mensagens consumidas por segundo (média)

Observações
5115350

Prod: 50

Cons: 150

15001600Broker estável, com mensagens enfileiradas em torno de 3 mil. Durante o período de execução, houveram variações na performance de consumo, superando muitas vezes a taxa de produção, o que permitiu a redução das mensagens enfileiradas.
10215350

Prod: 100

Cons: 150

24002100Broker estável, com aumento no acumulo de mensagens, apesar do número de consumers ser maior do que o de producers. Ultima medição registrou 100 mil mensagens enfileiradas.
15315350

Prod: 150

Cons: 150

30002700Broker estável, com mensagens enfileiradas batendo em 134 mil.

Considerações:

  • Recorreu-se ao uso das APIs de gerenciamento do RabbitMQ para realizar as medições. Neste cenário, o Management UI foi pouco útil devido o tempo excessivo de resposta.
  • Neste cenário, foi adotado um procedimento diferente dos outros cenários, de iniciar com um grande número de consumers (15 instâncias) ativos, comparado com os producers (5 instâncias).


Expandir
titleVersão 11

Cenário idêntico ao anterior, com ajuste da memória e CPU disponíveis para os testes.

Nó do clusterRabbitMQ
MemóriaCPUsVhostsMemory Watermark
8 Gb4/, app1, app23,1 Gb

Os parâmetros de deployment utilizados foram os seguintes:

DeploymentVhostPRODUCERSCONSUMERSQUEUE_ARGSQUEUE_PATTERN

QUEUE_

PATTERN_

FROM

QUEUE_

PATTERN_

TO

QOSVARIABLE_SIZEVARIABLE_RATE
Producer-1/100x-max-kength=20000perf-test-%02d110n/a

3000:60, 

1000:120, 

4000:60, 

500:300 

30:60, 

100:120, 

300:60, 

50:300 

Producer-2app11120
Producer-32130
Producer-4app23140
Producer-54150
Consumer-1/010x-max-length=20000perf-test-%02d110500n/an/a
Consumer-2app11120
Consumer-32130
Consumer-4app23140
Consumer-54150

A tabela abaixo demonstra o incremento de produtores e consumidores e resultados obtidos.

Instâncias Producer

Threads por fila

Instâncias Consumer

Threads por filaQtde. FilasConexões

Mensagens produzidas por segundo (média)

Mensagens consumidas por segundo (média)

Observações
5115350

Prod: 50

Cons: 150

36003600

Broker estável, mensagens enfileiradas em torno de 250.

Management UI respondendo no tempo às requisições.

10215350

Prod: 100

Cons: 150

32503250

Broker estável, mensagens enfileiradas em torno de 500.

Management UI respondendo.

15315350

Prod: 150

Cons: 150

83009400

Mensagens enfileiradas: 77 mil.

Management UI extremamente lento.

15325550

Prod: 150

Cons: 250

61005500

Os nós reiniciaram.

Reiniciando testes com nova estratégia de adição de agentes (consumers e producers).

5110250

Prod: 50

Cons: 100

15001500

Broker estável, Management UI respondendo. Mensagens enfileiradas: 11.

A partir deste ponto, adotou-se a estratégia de adicionar gradualmente os agentes, colocando mais consumers que producers para evitar o aumento repentino de mensagens enfileiradas.

10215350

Prod: 100

Cons: 150

70007200

Broker estável, Management UI respondendo.

Mensagens enfileiradas: 11 mil.

15320450

Prod: 150

Cons: 200

68006700

Broker estável, Management UI respondendo.

Mensagens enfileiradas: 10 mil.

15325550

Prod: 150

Cons: 250

70007500

Broker estável, Management UI respondendo.

Mensagens enfileiradas: 96 mil.

No início dos testes, foi nesta situação que os nós reiniciaram.

20430650

Prod: 200

Cons: 300

300012000

Broker estável. Mensagens enfileiradas: 44 mil

Memória: 800 Mb em cada nós.

Management UI parou de responder aqui.

25530650

Prod: 250

Cons: 300

??

Coleta por APIs não gerou resposta.

O limite de memória foi excedido e os nós reiniciaram.

Considerações:

  • Com mais memória e CPUs foi possível aumentar os patamares de operação do RabbitMQ e ampliar a carga aplicada ao broker.
  • A mudança de estratégia na adição dos agentes produtores e consumidores, fazendo de forma gradual, mostrou-se eficaz. Isso demonstra que é preciso administrar a entrada de novas conexões ao broker para evitar picos de memória e consequente reinício dos nós.


Conclusões

Com base em todos os testes realizados acima é possível concluir que:

  • É uma boa prática limitar a quantidade de mensagens por fila. A documentação elaborada pela empresa CloudAMQP  (vide referências) indica esta e outras recomendações para dar mais estabilidade e robustez ao broker.
  • Indicar a quantidade de mensagens recuperadas pelo consumidor também é uma boa prática, cuidando-se para que o valor informado não comprometa a memória alocada para o agente consumidor.
  • A separação por vhost é interessante para organizar e facilitar a gestão das filas e conexões no broker.
  • Deve-se ter cuidado com o uso do Management UI, pois a atualização frequente dos dados de monitoramento na interface acaba afetando a performance do broker. Por isso, o recomendado é desativar o refresh automático e consultar sob demanda.
  • Como alternativa, pode-se utilizar as APIs de monitoramento do RabbitMQ, restringindo o número de requisições e a quantidade de dados solicitados ao broker.
  • O uso de uma única instância do RabbitMQ (sem HA) só parece viável em cenários que necessitam de alto throughput e que a perda de mensagens não seja um problema para a aplicação. Do contrário, a configuração mínima do RabbitMQ requer pelo menos 2 nós trabalhando em HA.

Por fim, considerando os resultados do estudo, arriscamos fazer as indicações de uso conforme abaixo, a título de referência, visando estabilidade do broker e margem para eventuais picos de carga:

MemóriaCPUIndicação de uso
2 Gb1

Até 1000 msg/seg

50 produtores

100 consumidores

4 Gb2

Até 3000 msg/seg

100 produtores

150 consumidores

8 Gb4

Até 5000 msg/seg

200 produtores

250 consumidores

Referências consultadas

Ferramenta de teste de carga perf-test - https://rabbitmq.github.io/rabbitmq-perf-test/stable/htmlsingle/

Manual do RabbitMQ:

Getting started with RabbitMQ and CloudAMQP - https://www.cloudamqp.com/rabbitmq_ebook.html

Propriedades de página
Elaboração

 

Apresentação

 

Implementação

Não se aplica

Issue JIRA

Não se aplica


Índice