1.簡単な紹介
MQ
フルネーム(メッセージキュー)は、メッセージキューとも呼ばれ、非同期通信のミドルウェアです。郵便局と理解できます。送信者が郵便局にメッセージを配信すると、郵便局が特定のメッセージ受信者(消費者)にメッセージを送信するのを手伝ってくれます。特定の送信プロセスを気にする必要はありません。と時間、そしてそれは私の他のものに干渉しません。共通MQ
そこにkafka
、activemq
、zeromq
、rabbitmq
というように。
RabbitMQ
これは、AMQP
高い同時実行性を指向するerlanng
言語によって開発され、高い信頼性要件を持つリアルタイムメッセージングで使用され、多言語クライアントをサポートするプロトコルです。
基本コンセプト
Broker
:簡単に言えば、それはメッセージキューサーバーエンティティですExchange
:メッセージ交換。メッセージのルーティング先のルールとキューを指定します。Queue
:メッセージキューキャリア、各メッセージは1つ以上のキューに入れられますBinding
:バインディング、その役割は、ルーティングルールに従ってそれらexchange
をqueue
バインドすることですRouting Key
:exchange
メッセージ配信用のこのキーワードに応じたルーティングキーワードvhost
:仮想ホスト、broker
複数を1つに設定できvhost
、異なるユーザーの権限を分離するために使用されますproducer
:メッセージプロデューサーはメッセージを配信するプログラムですconsumer
:メッセージコンシューマーは、メッセージを受信するプログラムです。channel
:メッセージチャネル、クライアントの各接続で、複数を確立できchannel
、それぞれchannel
がセッションタスクを表します
一般的な参照シナリオ
- 電子メールの送信:ユーザーが登録すると、メッセージがユーザー
rabbitmq
に配信され、メッセージのコンシューマーが電子メールを非同期に送信します。これにより、システムの応答速度が向上します。 - トラフィックのピークカット:一般に、スパイクアクティビティで広く使用されています。スパイクにより、過剰なトラフィックが原因でアプリケーションがハングします。この問題を解決するために、通常、メッセージキューがアプリケーションのフロントエンドに追加されます。これはアクティビティの数を制御するために使用され、この特定のしきい値を超える注文は直接破棄されます。短期間の高流量破砕用途を緩和します。
- 注文タイムアウト:
rabbitmq
遅延キューを使用すると、注文タイムアウト機能を簡単に実現できます。たとえば、ユーザーは注文後30分を支払うことなく注文をキャンセルできます。
2.RabbitMQ環境を準備します
RabbitMQ
インストールの問題のため、ここでのテストでは、Docker環境を例として取り上げます。最初Linux
にdockerをインストールします。インストールしない場合は、docker install / dockerの一般的なコマンドを参照してください。
次に、ダウンロードして起動しますRabbitMQ
docker run -d --hostname my-rabbit --name pikachues-rabbit -p 5672:5672 -p15672:15672 rabbitmq:3-management
3.テスト
RabbitMQ
4つのメッセージ交換があります。それらは、直接(デフォルト)、ファンアウト、トピック、およびヘッダーです。スイッチのタイプが異なれば、メッセージ転送戦略も異なります。次のspringboot
4種類のメッセージ交換がテストされます。
0.テスト環境を準備します
頼る
<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>
構成ファイル
spring.rabbitmq.host=rabbitmq安装的ip地址
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.port=5672
1.直接
ユニキャストと同様に機能する直接交換は、と完全Exchange
に一致ROUTING_KEY
するキューにメッセージを送信します。
直接構成
@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");
}
}
メッセージ受信
@Component
public class DirectReceiver {
@RabbitListener(queues = "hello.pikachues")
public void handler1(String msg){
System.out.println(">>>handler"+msg);
}
}
テスト
@RunWith(SpringRunner.class)
@SpringBootTest
public class RabbitmqDemoApplicationTests {
@Autowired
RabbitTemplate rabbitTemplate;
@Test
public void direct() {
rabbitTemplate.convertAndSend("hello.pikachues","hello pikachues");
}
}
2.ファンアウト
ブロードキャストはスイッチの一種でROUTING_KEY
あり、メッセージの設定に関係なく、Exchange
バインドされているすべてのメッセージにメッセージを転送しますQueue
。
ファンアウト構成
@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());
}
}
メッセージ受信
@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);
}
}
テスト
@Test
public void testFanout(){
rabbitTemplate.convertAndSend(RabbitFanoutConfig.FANOUTNAME,null,"hello Fanout");
}
3.トピック
テーマ交換器は、マルチキャストのように動作し、Exchange
転送したメッセージとROUTING_KEY
同じパターンがこのようなすべてのキュー、一致するROUTING_KEY
ように*。*、結合様式に合わせて、転送* .stock、user.stockをと#.user .stock。#キュー。(*表は任意のフレーズに一致するものです。#は0個以上のフレーズに一致することを意味します)user.stock
Message
トピック構成
@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.#");
}
}
メッセージ受信
@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);
}
}
テスト
@Test
public void testTopic(){
rabbitTemplate.convertAndSend(RabbitTopicConfig.TOPICNAME,"xiaomi.news","小米新闻");
rabbitTemplate.convertAndSend(RabbitTopicConfig.TOPICNAME,"vivo.phone","小米手机");
rabbitTemplate.convertAndSend(RabbitTopicConfig.TOPICNAME,"huawei.phone","华为手机");
}
4.ヘッダー
メッセージ本文のヘッダーが一致します(無視)
ヘッダー構成
@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();
}
}
メッセージ受信
@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));
}
}
テスト
@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.その他
RabbitMQ
基本原則を理解したい場合は、この記事またはspringboot公式ウェブサイトの紹介をお読みください。