Garantia de confiabilidade da mensagem RabbitMQ
Na verdade, não há implementação de atraso de mensagem no RabbitMQ, mas podemos implementar atraso de mensagem por meio de TTL e roteamento de mensagens mortas.
1. Garantia do produtor
1. Notificação de falha
Quando os produtores enviam mensagens aos corretores, devem garantir a fiabilidade das mensagens. Existem duas soluções principais:
- Notificação de falha
- Confirmação do remetente
1. Notificação de falha : Se uma mensagem não for entregue à fila, uma notificação de falha aparecerá e a notificação de falha poderá ser habilitada.Na programação nativa, ao enviar uma mensagem, defina o sinalizador obrigatório para habilitar o modo de detecção de falha
. 2. Método de implementação:
configuração na primavera:
pring:
rabbitmq:
# 消息在未被队列收到的情况下返回
publisher-returns: true
No código java, o remetente precisa implementar a interface ReturnCallback para implementar a notificação de falha:
public class sendToMessage implements RabbitTemplate.ReturnCallback {
@Override
public void returnedMessage(Message message, int i, String s, String s1, String s2) {
}
@Override
public void returnedMessage(ReturnedMessage returned) {
RabbitTemplate.ReturnCallback.super.returnedMessage(returned);
}
}
3. O problema encontrado: se a mensagem for roteada corretamente para a fila, o editor não receberá nenhuma notificação. O problema é que ele não pode garantir que a mensagem seja publicada com sucesso, pois a mensagem roteada para a fila pode ser perdida
2. Confirmação do remetente
A confirmação do remetente significa que após o produtor entregar a mensagem, se o Broker receber a mensagem, ele dará uma resposta ao produtor, e o produtor receberá a resposta para confirmar se a mensagem é enviada ao Broker normalmente. Este método também é confiável. Garantia central de entrega sexual
- As mensagens são roteadas para a fila por meio do exchange exchange
- Envie a mensagem para a corretora, ou seja, para a central de câmbio
Obs: A falha no envio da confirmação só ocorrerá se houver um erro interno no RabbitMQ que não possa ser entregue.
1 Não roteável: Depois que a mensagem atual chega ao switch, a confirmação do remetente é bem-sucedida.
Em primeiro lugar, quando o switch RabbitMQ não é roteável, a mensagem não será entregue à fila, então aqui apenas o caminho para o switch. Quando a mensagem for enviada com sucesso Após o switch, uma operação de confirmação será realizada
Além disso, neste processo, após o produtor receber a mensagem de confirmação, porque a mensagem não pode ser roteada, a mensagem também é inválida e não pode ser entregue na fila, portanto, em circunstâncias normais, ela será usada junto com a notificação de falha , e geralmente será definido aqui. Modo obrigatório, se ocorrer falha, o ouvinte addReturnListener será chamado para processamento.
2. Pode ser roteada; contanto que a mensagem possa chegar à fila, ela pode ser confirmada. Geralmente,
as mensagens que não podem ser roteadas aparecerão quando ocorrer um erro interno no RabbitMQ. Depois que a mensagem for entregue a todas as filas correspondentes, o O broker enviará uma confirmação ao produtor (contendo o ID exclusivo da mensagem), isso permite ao produtor saber que a mensagem chegou corretamente à fila de destino.
Se a mensagem e a fila forem duráveis, a mensagem de confirmação será enviada depois que a mensagem for gravada no disco, e o campo delivery-tag na mensagem de confirmação enviada de volta ao produtor pelo corretor contém o número de série da mensagem de confirmação
3. Método de implementação
Configuração na primavera:
spring:
rabbitmq:
# 开启消息确认机制
publisher-confirm-type: correlated
No código java, o remetente precisa implementar a interface ConfirmCallback para implementar a notificação de falha.
public class sendToMessage implements RabbitTemplate.ConfirmCallback {
@Override
public void confirm(CorrelationData correlationData, boolean b, String s) {
}
}
3. Corretor perde mensagem
Habilite a persistência do RabbitMQ, ou seja, após a gravação da mensagem, ela será persistida no disco, mesmo que o mq desligue neste momento, os dados armazenados anteriormente serão lidos automaticamente após a reinicialização.
1. Fila de persistência
@Bean
public Queue queue(){
return new Queue(queueName,true);
}
2. Trocador persistente
@Bean
DirectExchange directExchange() {
return new DirectExchange(exchangeName,true,false);
}
3.Enviar mensagens persistentes
Ao enviar uma mensagem, defina o deliveryMode=2 da mensagem
Nota: Se você usar SpringBoot, deliveryMode=2 será definido automaticamente ao enviar uma mensagem e não há necessidade de configurá-lo manualmente.
2. Confiabilidade da mensagem do consumidor (confirmação manual do consumidor)
1. O padrão do RabbitMQ é confirmação automática, que precisa ser modificada para confirmação manual, ou seja, após seu próprio programa determinar que a mensagem foi processada, você pode enviar a confirmação manualmente. Neste momento, se você encontrar uma situação em que o o processo trava sem processar a mensagem, devido a Sem enviar a confirmação, o RabbitMQ não excluirá a mensagem, mas a enviará a outros consumidores para processamento, mas a mensagem não será perdida.
2.arquivo de configuração do spring
spring:
rabbitmq:
listener:
simple:
acknowledge-mode: manual # 手动ack
3. Introdução de parâmetros
reconhecimento-modo: manual significa ativar a confirmação manual. Os outros dois valores deste item de configuração são nenhum e automático.
- auto: O consumidor decide se deseja enviar ack ou nack com base no fato de o programa ser executado normalmente ou lançar uma exceção. Não confunda none com auto.
- manual: confirmação manual, o usuário deve enviar manualmente a confirmação ou nack
- nenhum: nenhum mecanismo de confirmação
4. Realização do consumidor
public class sendToMessage {
@RabbitHandler
public void processOrder(Message massage, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
channel.basicAck(tag, false);
}
}
3. Análise de confiabilidade empresarial
1. Perda de mensagem: Neste cenário de negócios, o usuário inicia uma solicitação de táxi. Se a mensagem do usuário for perdida, não haverá impacto no negócio geral. O usuário pode iniciar a operação de táxi novamente. A probabilidade deste problema de perda de mensagem é muito baixo, e um design simplificado pode ser realizado., se houver falha no envio, basta reverter a operação no redis.
2. Verificação de idempotência: Devido ao uso da fila de atraso, não há necessidade de verificação de idempotência para este negócio, pois se a chave de classificação do usuário redis existir no primeiro tempo limite, ela será excluída. Próximo Um valor que não está disponível no redis é excluído uma vez.Esta operação é idempotente, portanto não há necessidade de considerar a idempotência.
3. Reversão de dados: Embora não seja necessário garantir que a mensagem não seja perdida e que a mensagem seja idempotente, é necessário considerar que se ocorrer um problema, o valor-chave inserido no Redis precisa ser revertido para evitar o julgamento normal do negócio seja afetado