Práticas recomendadas do Amazon MQ para RabbitMQ - Amazon MQ

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Práticas recomendadas do Amazon MQ para RabbitMQ

Use esta seção como referência para localizar rapidamente as recomendações para maximizar a performance e minimizar os custos de taxa de transferência para trabalhar com agentes do RabbitMQ no Amazon MQ.

Importante

Atualmente, o Amazon MQ não é compatível com transmissões, nem com o uso do registro estruturado em JSON, apresentado no RabbitMQ 3.9.x.

Importante

O Amazon MQ para RabbitMQ não permite o nome de usuário “convidado” e excluirá a conta de convidado padrão quando você criar um agente. O Amazon MQ também excluirá periodicamente qualquer conta de “convidado” criada pelo cliente.

Escolha o tipo correto de instância do agente para obter o melhor throughput

O throughput de mensagens de um tipo de instância do agente depende do caso de uso da aplicação. Tipos menores de instância do agente, como t3.micro, devem ser usados somente para testar o desempenho da aplicação. Usar essas microinstâncias antes de usar instâncias maiores na produção pode melhorar o desempenho da aplicação e ajudar você a reduzir os custos de desenvolvimento. Em tipos de instância m5.large e superiores, você pode usar implantações de cluster para obter alta disponibilidade e durabilidade de mensagens. Tipos maiores de instância do agente conseguem lidar com níveis de produção de clientes e filas, alto throughput, mensagens na memória e mensagens redundantes. Para obter mais informações sobre como escolher o tipo de instância correto, consulteDiretrizes de dimensionamento do Amazon MQ para RabbitMQ.

Usar vários canais

Para evitar a perda de conexão, use vários canais em uma única conexão. As aplicações devem evitar uma relação de conexão de 1:1 com o canal. Recomendamos usar uma conexão por processo e um canal por thread. Evite o uso excessivo de um canal para impedir vazamentos no canal.

Usar mensagens persistentes e filas duráveis

Mensagens persistentes podem ajudar a evitar a perda de dados em situações em que um agente falha ou reinicia. Mensagens persistentes são gravadas no disco assim que chegam. Ao contrário das filas lazy, no entanto, as mensagens persistentes são armazenadas em cache tanto na memória quanto no disco, a menos que o agente necessite de mais memória. Nos casos em que mais memória é necessária, as mensagens são removidas da memória pelo mecanismo do agente RabbitMQ que gerencia o armazenamento de mensagens no disco, comumente chamado de camada de persistência.

Para habilitar a persistência de mensagens, você pode declarar suas filas como durable e definir o modo de entrega de mensagens como persistent. O exemplo a seguir demonstra declarar uma fila durável usando a biblioteca do cliente Java RabbitMQ. Ao trabalhar com o AMQP 0-9-1, você pode marcar mensagens como persistentes definindo o modo de entrega como “2”.

boolean durable = true; channel.queueDeclare("my_queue", durable, false, false, null);

Depois de configurar sua fila como durável, você pode enviar uma mensagem persistente para a fila definindo MessageProperties como PERSISTENT_TEXT_PLAIN, da forma mostrada no exemplo a seguir.

import com.rabbitmq.client.MessageProperties; channel.basicPublish("", "my_queue", MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());

Mantenha as filas curtas

Em implantações de cluster, filas com um grande número de mensagens podem levar à utilização excessiva de recursos. Quando um agente é utilizado em excesso, a reinicialização de um agente do Amazon MQ para RabbitMQ pode causar maior degradação da performance. Se reinicializados, os agentes usados em excesso podem deixar de responder no estado REBOOT_IN_PROGRESS.

Durante as janelas de manutenção, o Amazon MQ executa todos os trabalhos de manutenção um nó de cada vez para garantir que o agente permaneça operacional. Como resultado, as filas podem precisar sincronizar à medida que cada nó retoma a operação. Durante a sincronização, as mensagens que precisam ser replicadas em espelhos são carregadas na memória do volume correspondente do Amazon Elastic Block Store (Amazon EBS) para serem processadas em lotes. O processamento de mensagens em lotes permite que as filas sejam sincronizadas mais rapidamente.

Se as filas forem mantidas curtas e as mensagens forem pequenas, as filas serão sincronizadas com êxito e retomarão a operação conforme esperado. No entanto, se a quantidade de dados em um lote se aproximar do limite de memória do nó, o nó gera um alarme de memória alta, pausando a sincronização de fila. Você pode confirmar o uso da memória comparando as métricas do nó RabbitMemUsed e do RabbitMqMemLimit broker em CloudWatch. A sincronização não pode ser concluída até que as mensagens sejam consumidas ou excluídas ou o número de mensagens no lote seja reduzido.

Se a sincronização de filas estiver pausada para uma implantação de cluster, recomendamos consumir ou excluir mensagens para diminuir o número de mensagens em filas. Quando a profundidade da fila for reduzida e a sincronização da fila for concluída, o status do agente mudará para RUNNING. Para resolver uma sincronização de fila pausada, você também pode aplicar uma política para reduzir o tamanho do lote de sincronização de filas.

Você também pode definir políticas de exclusão automática e TTL para reduzir proativamente o uso de recursos, bem como reduzir ao mínimo o NACKs alcance dos consumidores. O enfileiramento de mensagens na corretora consome muita CPU, portanto, um grande número de mensagens pode afetar o desempenho da corretora. NACKs

Configurar a confirmação do publicador e a confirmação de entrega do consumidor

O processo de confirmar que uma mensagem foi enviada ao agente é conhecido como confirmação do publicador. As confirmações do publicador avisam a aplicação quando as mensagens foram armazenadas de forma confiável. As confirmações do publicador também podem ajudar a controlar a taxa de mensagens armazenadas no agente. Sem as confirmações do publicador, não há confirmação de que uma mensagem foi processada com sucesso, e seu agente talvez envie mensagens que não consegue processar.

De modo similar, quando uma aplicação cliente envia uma confirmação de entrega e consumo de mensagens de volta ao agente, isso é conhecido como confirmação de entrega do consumidor. Os dois tipos de confirmação são essenciais para garantir a segurança dos dados ao trabalhar com agentes do RabbitMQ.

A confirmação de entrega do consumidor geralmente é configurada na aplicação do cliente. Ao trabalhar com o AMQP 0-9-1, a confirmação pode ser habilitada configurando o método basic.consume. Os clientes AMQP 0-9-1 também podem configurar as confirmações do publicador enviando o método confirm.select.

Normalmente, a confirmação de entrega está habilitada em um canal. Por exemplo, ao trabalhar com a biblioteca do cliente Java RabbitMQ, você pode usar o Channel#basicAck para configurar um reconhecimento positivo basic.ack, conforme mostrado no exemplo a seguir.

// this example assumes an existing channel instance boolean autoAck = false; channel.basicConsume(queueName, autoAck, "a-consumer-tag", new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { long deliveryTag = envelope.getDeliveryTag(); // positively acknowledge a single delivery, the message will // be discarded channel.basicAck(deliveryTag, false); } });
nota

Mensagens não reconhecidas devem ser armazenadas em cache na memória. Você pode limitar o número de mensagens que um consumidor busca antecipadamente configurando Pré-busca para uma aplicação do cliente.

Você pode configurar o consumer_timeout para detectar quando os consumidores não confirmarem as entregas. Se o consumidor não enviar uma confirmação dentro do tempo limite, o canal será fechado e você receberá PRECONDITION_FAILED. Para diagnosticar o erro, use a UpdateConfigurationAPI para aumentar o consumer_timeout valor.

Configurar pré-busca

Você pode usar o valor de pré-busca RabbitMQ para otimizar como seus consumidores consomem mensagens. O RabbitMQ implementa o mecanismo de pré-busca do canal fornecido pelo AMQP 0-9-1 aplicando a contagem de pré-busca aos consumidores em oposição aos canais. O valor de pré-busca é usado para especificar quantas mensagens estão sendo enviadas ao consumidor em um determinado momento. Por padrão, o RabbitMQ define um tamanho ilimitado de buffer para aplicações do cliente.

Há muitos fatores a serem considerados ao definir uma contagem de pré-busca para seus consumidores RabbitMQ. Primeiro, considere o ambiente e a configuração dos seus consumidores. Como os consumidores precisam manter todas as mensagens na memória enquanto estão sendo processadas, um alto valor de pré-busca pode ter um impacto negativo na performance de seus consumidores e, em alguns casos, pode resultar em um consumidor potencialmente travando tudo. Da mesma forma, o próprio agente RabbitMQ mantém todas as mensagens que envia armazenadas em cache na memória até receber reconhecimento do consumidor. Um valor de pré-busca alto pode fazer com que o servidor RabbitMQ fique sem memória rapidamente se a confirmação automática não estiver configurada para os consumidores e se os consumidores demorarem um tempo relativamente longo para processar mensagens.

Com as considerações acima em mente, recomendamos sempre definir um valor de pré-busca para evitar situações em que um agente RabbitMQ ou seus consumidores ficam sem memória devido a um grande número de mensagens não processadas ou não confirmadas. Se você precisar otimizar seus agentes para processar grandes volumes de mensagens, você pode testar seus agentes e consumidores usando uma gama de contagens de pré-busca para determinar o valor em que ponto a sobrecarga de rede se torna em grande parte insignificante em comparação com o tempo que um consumidor leva para processar mensagens.

nota
  • Se as aplicações do seu cliente tiverem configurado para confirmar automaticamente a entrega de mensagens aos consumidores, a definição de um valor de pré-busca não terá efeito.

  • Todas as mensagens pré-buscadas são removidas da fila.

O exemplo a seguir demonstra a configuração de um valor de pré-busca de 10 para um único consumidor usando a biblioteca do cliente Java RabbitMQ.

ConnectionFactory factory = new ConnectionFactory(); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.basicQos(10, false); QueueingConsumer consumer = new QueueingConsumer(channel); channel.basicConsume("my_queue", false, consumer);
nota

Na biblioteca do cliente Java RabbitMQ, o valor padrão para global está definido como false, de modo que o exemplo acima pode ser escrito simplesmente como channel.basicQos(10).

Configurar o Celery

O Python Celery envia muitas mensagens desnecessárias que podem dificultar a localização e o processamento das informações úteis. Para reduzir o ruído e facilitar o processamento, insira o comando a seguir:

celery -A app_name worker --without-heartbeat --without-gossip --without-mingle

Recuperação automática de falhas de rede

Recomendamos sempre habilitar a recuperação automática de rede para evitar tempo de inatividade significativo nos casos em que as conexões do cliente com os nós RabbitMQ falham. A biblioteca do cliente Java RabbitMQ é compatível com a recuperação automática de rede por padrão, começando com a versão 4.0.0.

A recuperação automática de conexão é acionada se uma exceção não processada for lançada no loop de E/S da conexão, se um tempo limite de operação de leitura de soquete for detectado ou se o servidor perder uma pulsação.

Nos casos em que a conexão inicial entre um cliente e um nó RabbitMQ falha, a recuperação automática não será acionada. Recomendamos escrever o código da aplicação para levar em conta as falhas de conexão iniciais tentando a conexão novamente. O exemplo a seguir demonstra a repetição de falhas iniciais de rede usando a biblioteca de cliente Java RabbitMQ.

ConnectionFactory factory = new ConnectionFactory(); // enable automatic recovery if using RabbitMQ Java client library prior to version 4.0.0. factory.setAutomaticRecoveryEnabled(true); // configure various connection settings try { Connection conn = factory.newConnection(); } catch (java.net.ConnectException e) { Thread.sleep(5000); // apply retry logic }
nota

Se uma aplicação fecha uma conexão usando o método Connection.Close, a recuperação automática de rede não será ativada ou acionada.