Carte de visite personnelle :
Blogueur: Ivrogneᝰ.
Profil personnel: Offrez-vous du vin et utilisez l'énergie du vin pour lutter pour un avenir.
Cet article est inspirant: Quand nous voyageons à trois ensemble, nous devons être mon professeur.
Ce projet est basé sur Java "SpringCloud Microservice Technology Stack" par le programmeur cheval noir de la station B , SpringCloud+RabbitMQ+Docker+Redis+search+distributed
[SpringCloud+RabbitMQ+Docker+Redis+search+explication détaillée et distribuée du système cours sur la pile technologique des microservices Springcloud | Programmeur Dark Horse Microservices Java] Cliquez pour regarder
Table des matières
2. Fiabilité des messages
De l'envoi d'un message à sa réception par le consommateur, plusieurs processus sont gérés :
Chacune de ces étapes peut entraîner une perte de message. Les raisons courantes de perte sont les suivantes :
- Perdu lors de l'envoi :
- Le message envoyé par le producteur n'est pas remis à l'échange
- Le message n'atteint pas la file d'attente après avoir atteint l'échange
- MQ est en panne et la file d'attente perd des messages
- Après avoir reçu le message, le consommateur plante sans le consommer.
En réponse à ces problèmes, RabbitMQ apporte des solutions :
- Mécanisme de confirmation du producteur
- persistance mq
- Mécanisme de confirmation du consommateur
- Mécanisme de nouvelle tentative d'échec
Tout d'abord, importez le projet de projet (mq-advanced-demo) fourni par le matériel préalable au cours.
1. Confirmation du message du producteur
RabbitMQ fournit un mécanisme de confirmation d'éditeur pour éviter la perte de message lors de l'envoi à MQ. Ce mécanisme doit attribuer un identifiant unique à chaque message. Une fois le message envoyé à MQ, un résultat sera renvoyé à l'expéditeur, indiquant si le message a été traité avec succès.
Il existe deux manières de renvoyer les résultats :
- confirmation de l'éditeur, confirmation de l'expéditeur
- Le message est transmis avec succès au commutateur et un accusé de réception est renvoyé.
- Le message n'est pas transmis au commutateur et nack est renvoyé.
- retour éditeur, accusé de réception de l'expéditeur
- Le message est transmis au commutateur, mais n'est pas acheminé vers la file d'attente. Renvoie ACK et la raison de l’échec du routage.
Avis:
- Modifier le paramètre
Tout d'abord, modifiez l'adresse IP, le nom d'utilisateur, le mot de passe et d'autres configurations de lapinmq dans le fichier application.yml du service éditeur, et ajoutez le contenu suivant :
spring:
rabbitmq:
publisher-confirm-type: correlated
publisher-returns: true
template:
mandatory: true
illustrer:
publish-confirm-type
: Activez la confirmation de l'éditeur. Deux types sont pris en charge ici :
simple
: Attendez le résultat de la confirmation de manière synchrone jusqu'à l'expiration du délaicorrelated
: Rappel asynchrone, définissez ConfirmCallback, MQ rappellera ce ConfirmCallback lors du renvoi du résultatpublish-returns
: Activez la fonction de publication-retour, qui est également basée sur le mécanisme de rappel, mais définit ReturnCallbacktemplate.mandatory
: Définissez la stratégie en cas d'échec du routage des messages. true, appelle ReturnCallback ; false : supprime le message directement
- Définir le rappel de retour
每个RabbitTemplate只能配置一个ReturnCallback
, il doit donc être configuré lors du chargement du projet :
Modifiez le service éditeur et ajoutez-en un :
package cn.itcast.mq.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
@Slf4j
@Configuration
public class CommonConfig implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//获取rabbitTemplate
RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);
//设置ReturnCallback
rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
log.error("消息发送失败,应答码:{},原因:{},交换机:{},路由键:{},消息:{}",
replyCode, replyText, exchange, routingKey, message);
});
}
}
- DefineConfirmCallback
ConfirmCallback peut être spécifié lors de l'envoi d'un message, car la logique de chaque traitement métier confirmant le succès ou l'échec n'est pas nécessairement la même.
Dans la classe cn.itcast.mq.spring.SpringAmqpTest du service éditeur, définissez une méthode de test unitaire :
package cn.itcast.mq.spring;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.UUID;
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringAmqpTest {
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void testSendMessage2SimpleQueue() throws InterruptedException {
//消息体
String message = "hello, spring amqp!";
//设置唯一ID。封装到CorrelationData中
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
//添加callback
correlationData.getFuture().addCallback(
result -> {
if (result.isAck()){
//ack,发送成功
log.debug("消息发送交换机成功,ID:{}", correlationData.getId());
}else {
//nock,发送失败
log.error("消息发送交换机失败,ID:{}", correlationData.getId());
}
},
ex -> log.error("消息发送队列失败,ID:{},原因:{}", correlationData.getId(), ex.getMessage())
);
//发送消息
rabbitTemplate.convertAndSend("amq.direct", "amq", message, correlationData);
}
}
Test :
ajoutez l'échange et la file d'attente correspondant au code côté navigateur mq, et définissez la clé de routage du contact. file d'attente
d'échange
Résultats clés de routage
: