1. Kurze Einführung
MQ
Der vollständige Name (Message Queue), auch als Message Queue bezeichnet, ist eine Middleware für die asynchrone Kommunikation. Es kann als Post verstanden werden. Der Absender übermittelt die Nachricht an die Post, und dann hilft uns die Post, sie an den spezifischen Nachrichtenempfänger (Verbraucher) zu senden. Wir müssen uns nicht um den spezifischen Sendevorgang kümmern und Zeit, und es wird meine anderen Dinge nicht stören. Häufig MQ
gibt kafka
, activemq
, zeromq
, rabbitmq
und so weiter.
RabbitMQ
Es handelt sich um ein AMQP
Protokoll, erlanng
das von einer Sprache entwickelt wurde, die auf hohe Parallelität ausgerichtet ist , in Echtzeitnachrichten mit hohen Zuverlässigkeitsanforderungen verwendet wird und mehrsprachige Clients unterstützt.
Basiskonzept
Broker
: Einfach ausgedrückt, es ist die Entität des NachrichtenwarteschlangenserversExchange
: Nachrichtenaustausch, der die Regeln und Warteschlangen angibt, an die Nachrichten weitergeleitet werdenQueue
: Nachrichtenwarteschlangenträger, jede Nachricht wird in eine oder mehrere Warteschlangen gestelltBinding
: Bindung, ist seine Rolleexchange
undqueue
mit den Routing - Regeln binden sie in ÜbereinstimmungRouting Key
: Routing-Schlüsselwortexchange
gemäß diesem Schlüsselwort für die Nachrichtenübermittlungvhost
: Virtueller Host,broker
kann mehrere in einem einrichtenvhost
, um die Berechtigungen verschiedener Benutzer zu trennenproducer
: Der Nachrichtenproduzent ist das Programm, das die Nachricht übermitteltconsumer
: Der Nachrichtenkonsument ist das Programm, das die Nachricht empfängtchannel
: Nachrichtenkanal, in jeder Verbindung des Clients können mehrere eingerichtet werdenchannel
, die jeweilschannel
eine Sitzungsaufgabe darstellen
Allgemeine Referenzszenarien
- E-Mail-Versand: Nachdem sich der Benutzer registriert hat, wird die Nachricht an den Benutzer
rabbitmq
übermittelt, und der Nachrichtenkonsument sendet die E-Mail asynchron, wodurch die Systemantwortgeschwindigkeit verbessert wird - Reduzierung der Verkehrsspitzen: Im Allgemeinen wird sie häufig in der Spike-Aktivität verwendet. Die Spitze führt dazu, dass die Anwendung aufgrund von übermäßigem Verkehr hängen bleibt. Um dieses Problem zu lösen, wird die Nachrichtenwarteschlange normalerweise dem Front-End der Anwendung hinzugefügt. Es wird verwendet, um die Anzahl der Aktivitäten zu steuern, und Aufträge, die diesen bestimmten Schwellenwert überschreiten, werden direkt verworfen. Entlasten Sie kurzfristige Brechanwendungen mit hohem Durchfluss.
- Bestellzeitlimit: Durch die Verwendung
rabbitmq
der Verzögerungswarteschlange kann die Bestellzeitlimitfunktion leicht realisiert werden. Beispielsweise storniert der Benutzer die Bestellung, ohne 30 Minuten nach der Bestellung zu zahlen
2. Bereiten Sie die RabbitMQ-Umgebung vor
Aufgrund der RabbitMQ
Installationsprobleme wird hier die Docker-Umgebung als Beispiel verwendet. Linux
Installieren Sie Docker zuerst . Wenn Sie dies nicht tun, können Sie auf die allgemeinen Docker-Installations- / Docker-Befehle verweisen
Dann herunterladen und startenRabbitMQ
docker run -d --hostname my-rabbit --name pikachues-rabbit -p 5672:5672 -p15672:15672 rabbitmq:3-management
3. Testen
RabbitMQ
Es gibt vier Nachrichtenaustausche. Sie sind direkt (Standard), Fanout, Thema und Header. Verschiedene Arten von Switches haben unterschiedliche Strategien zur Nachrichtenweiterleitung. Die folgenden springboot
vier Arten des Nachrichtenaustauschs werden getestet.
0. Bereiten Sie die Testumgebung vor
verlassen Sie sich
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Konfigurationsdatei
spring.rabbitmq.host=rabbitmq安装的ip地址
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.port=5672
1.direkt
Der direkte Austausch, der ähnlich wie Unicast funktioniert, Exchange
sendet Nachrichten an ROUTING_KEY
eine Warteschlange , die genau übereinstimmt .
direkte Konfiguration
@Configuration
public class RabbitDirectConfig {
public final static String DIRECTNAME = "pikachues-direct";
@Bean
Queue queue() {
return new Queue("hello.pikachues");
}
@Bean
DirectExchange directExchange(){
return new DirectExchange(DIRECTNAME,true,false);
}
@Bean
Binding binding(){
return BindingBuilder.bind(queue()).to(directExchange()).with("direct");
}
}
Nachrichtenempfang
@Component
public class DirectReceiver {
@RabbitListener(queues = "hello.pikachues")
public void handler1(String msg){
System.out.println(">>>handler"+msg);
}
}
Prüfung
@RunWith(SpringRunner.class)
@SpringBootTest
public class RabbitmqDemoApplicationTests {
@Autowired
RabbitTemplate rabbitTemplate;
@Test
public void direct() {
rabbitTemplate.convertAndSend("hello.pikachues","hello pikachues");
}
}
2.fanout
Broadcasting ist eine Art Schalter, der unabhängig von der ROUTING_KEY
Einstellung der Nachricht Exchange
die Nachricht an alle gebundenen weiterleitet Queue
.
Fanout-Konfiguration
@Configuration
public class RabbitFanoutConfig {
public static final String FANOUTNAME = "pikachues-fanout";
@Bean
Queue queueOne(){
return new Queue("queue-one");
}
@Bean
Queue queueTwo(){
return new Queue("queue-two");
}
@Bean
FanoutExchange fanoutExchange(){
return new FanoutExchange(FANOUTNAME,true,false);
}
@Bean
Binding bindingOne(){
return BindingBuilder.bind(queueOne()).to(fanoutExchange());
}
@Bean
Binding bindingTwo(){
return BindingBuilder.bind(queueTwo()).to(fanoutExchange());
}
}
Nachrichtenempfang
@Component
public class FanoutReceiver {
@RabbitListener(queues = "queue-one")
public void handler1(String msg){
System.out.println("FanoutReceiver:handler1"+msg);
}
@RabbitListener(queues = "queue-two")
public void handler2(String msg){
System.out.println("FanoutReceiver:handler2"+msg);
}
}
Prüfung
@Test
public void testFanout(){
rabbitTemplate.convertAndSend(RabbitFanoutConfig.FANOUTNAME,null,"hello Fanout");
}
3. Thema
Der Themenaustauscher funktioniert wie Multicast, Exchange
leitet die Nachrichten weiter und ROUTING_KEY
das gleiche Muster stimmt mit allen Warteschlangen überein, z. ROUTING_KEY
B. user.stock
die Message
Weiterleitungen, um dem Bindungsmodus zu entsprechen. * .Stock, user.stock, *. * Und # .user .stock. # Die Warteschlange. (* Die Tabelle muss mit einer beliebigen Phrase übereinstimmen. # Bedeutet, dass 0 oder mehr Phrasen übereinstimmen.)
Themenkonfiguration
@Configuration
public class RabbitTopicConfig {
public static final String TOPICNAME = "pikachues-topic";
@Bean
TopicExchange topicExchange(){
return new TopicExchange(TOPICNAME,true,false);
}
@Bean
Queue xiaomi(){
return new Queue("xiaomi");
}
@Bean
Queue huaiwei(){
return new Queue("huawei");
}
@Bean
Queue phone(){
return new Queue("phone");
}
@Bean
Binding xiaomiBinding(){
return BindingBuilder.bind(xiaomi()).to(topicExchange()).with("xiaomi.#");
}
@Bean
Binding huaiweiBinding(){
return BindingBuilder.bind(huaiwei()).to(topicExchange()).with("huawei.#");
}
@Bean
Binding phoneBinding(){
return BindingBuilder.bind(phone()).to(topicExchange()).with("#.phone.#");
}
}
Nachrichtenempfang
@Component
public class TopicReceiver {
@RabbitListener(queues = "xiaomi")
public void handler1(String msg) {
System.out.println("TopicReceiver:handler1:" + msg);
}
@RabbitListener(queues = "huawei")
public void handler2(String msg) {
System.out.println("TopicReceiver:handler2:" + msg);
}
@RabbitListener(queues = "phone")
public void handler3(String msg) {
System.out.println("TopicReceiver:handler3:" + msg);
}
}
Prüfung
@Test
public void testTopic(){
rabbitTemplate.convertAndSend(RabbitTopicConfig.TOPICNAME,"xiaomi.news","小米新闻");
rabbitTemplate.convertAndSend(RabbitTopicConfig.TOPICNAME,"vivo.phone","小米手机");
rabbitTemplate.convertAndSend(RabbitTopicConfig.TOPICNAME,"huawei.phone","华为手机");
}
4.headers
Der Header des Nachrichtentexts stimmt überein (ignorieren)
Header-Konfiguration
@Configuration
public class RabbitHeaderConfig {
public static final String HEADERNAME = "pikachues-header";
@Bean
HeadersExchange headersExchange(){
return new HeadersExchange(HEADERNAME, true,false);
}
@Bean
Queue queueName(){
return new Queue("name-queue");
}
@Bean
Queue queueAge(){
return new Queue("age-queue");
}
@Bean
Binding bindingName(){
Map<String,Object> map = new HashMap<>();
map.put("name","pikachues");
return BindingBuilder.bind(queueName()).to(headersExchange()).whereAny(map).match();
}
@Bean
Binding bindingAge(){
return BindingBuilder.bind(queueAge()).to(headersExchange()).where("age").exists();
}
}
Nachrichtenempfang
@Component
public class HeaderReceiver {
@RabbitListener(queues = "name-queue")
public void handler1(byte[] msg) {
System.out.println("HeaderReceiver:handler1:" + new String(msg, 0, msg.length));
}
@RabbitListener(queues = "age-queue")
public void handler2(byte[] msg) {
System.out.println("HeaderReceiver:handler2:" + new String(msg, 0, msg.length));
}
}
Prüfung
@Test
public void testHeaders(){
Message nameMsg = MessageBuilder.withBody("hello pikachues".getBytes()).setHeader("name","pikachues").build();
Message ageMsg = MessageBuilder.withBody("hello 99".getBytes()).setHeader("age","99").build();
rabbitTemplate.convertAndSend(RabbitHeaderConfig.HEADERNAME,null,nameMsg);
rabbitTemplate.convertAndSend(RabbitHeaderConfig.HEADERNAME,null,ageMsg);
}
4. Andere
Wenn Sie RabbitMQ
die Grundprinzipien verstehen möchten , lesen Sie bitte diesen Artikel oder die Einführung der offiziellen Springboot-Website .