Springboot統合RabbitMp

RabbitMQの

これは、メッセージキューであり、主にアプリケーション・プロセスを分離する非同期を実装するために使用されますが、メッセージバッファ、ニュース配信の役割を果たすことができます。

メッセージングミドルウェア、インターネットを使用して、より多くの企業、またニュースがちょうどRocketMQアリは、Apacheに寄付されます見て、当然のことながら、今日の主人公は、まだのRabbitMQを話します。主な役割は、ミドルウェアの標準的な使用量がキューにメッセージを生成するための最も生産され、消費者は生産者は消費者が誰であるかを気にしない、消費者が気にしない、キューからメッセージをピックアップし、処理し、メッセージングミドルウェア切り離されていますニュースの生産の人、デカップリングの目的を達成するようになっています。ように、支持分散トランザクションのRPCコールを、そして:分散システムでは、メッセージキューは、次のような多くの他の態様では、使用されるであろう。

以前のActiveMQを使用していた、実際の生産使用中、多くの情報へのネットワークアクセスにおけるいくつかのマイナーな問題があった、ActiveMQのはRabbitMQの、RabbitMQの高可用性、高パフォーマンス、柔軟性、およびいくつかの機能を使用置き換えるためにしようとすることを決めましたそれは私たちにこの記事を整理し、いくつかの情報へのアクセスを集めました。

RabbitMQのご紹介

RabbitMQのメッセージング・ミドルウェアは、AMQP(アドバンスト・メッセージキューProtocol)を実装し、使いやすさ、拡張性、高可用性の観点から、分散システムに保存する金融システムとメッセージを転送で生まれ、そしてとてもよくやっています。RabbitMQのは、システムと実装の間で双方向のデカップリングを達成するために主にあります。プロデューサーは、大量のデータを生成するときに、消費者は、我々は、中間層を必要とし、高速で消費することはできません。このデータを保存します。

AMQP、すなわちアドバンストメッセージキュープロトコル、高度なメッセージキュープロトコルは、メッセージ指向ミドルウェアの設計のためのオープンな標準のアプリケーション層のプロトコルです。コンポーネント、ユーザのプレゼンス情報を知らなくても、メッセージの送信者、およびその逆の間のデカップリングのために主にメッセージミドルウェア。AMQP主な機能は、キューのメッセージ、ルーティングされ(点を含むとパブリッシュ/サブスクライブ)、信頼性、安全性。

RabbitMQのAMQPは、Erlangの言語を使用して、オープンソースの実装、サーバ側であるようなクライアントの様々なサポート:PythonやRubyの、.NETやJava、JMS、C、PHP、ActionScriptの、XMPP、STOMP、およびAJAXのサポートを。使用、スケーラビリティ、高可用性のしやすさの点ではストアアンドフォワードメッセージのための分散システムでは、ととてもよくやって。

関連概念

通常、我々は、キューサービスの話を、3つの概念が存在します。この基本的な考え方にメッセージ、RabbitMQのを受信したメッセージのキューは、人とメッセージキューの間の抽象化レイヤを行い、スイッチを追加(交換)。そのようなメッセージキューと直接結合していないが、今度は、スイッチは、次にスケジューリングポリシーに従ってメッセージキューを与える、スイッチによってメッセージにメッセージとなります。

画像

PはそれがRabbitMQのメッセージングプロセスであり、生産者の左側の略です。
その中間体は、スイッチおよびキューを含むRabbitMQの、です。
Cはそれを取るためにRabbitMQのメッセージングプロセスであり、消費者の権利を表します。
仮想ホスト、スイッチ、キュー、およびバインディング:だから、もっと重要な概念の一つが4、すなわちを持っています。

ウェブホスティング:Webホスティングは、スイッチ、キューとバインディングのセットを保持しています。なぜ我々は、複数の仮想ホストには必要なのでしょうか?非常にシンプルな、ユーザーが唯一の仮想ホストに制御細かにアクセスすることができ、それらをRabbitMQの。あなたがアクセスする必要があるのであれば、スイッチは、それぞれAとBの仮想ホストを作成する必要があり、グループAグループB /キュー/バインディングを禁止しています。各サーバは、「/。」デフォルトのRabbitMQ仮想ホストを持っています
スイッチ:Exchangeへのバインドをキューいない場合は、メッセージを転送するための交換が、それは保存をしない、それはプロデューサーによって送信されたメッセージの上に直接落ちます。ルーティングキー:ここではより多くの重要な概念があります。機会が対応するキューに転送対話するようにスイッチへのメッセージは、その後、どのキューに転送されているもの、それはルーティングキーに応じて必要です。
結合:スイッチが必要であり、多くの関係に多く、上記のようにこれは、キューに結合されます。
スイッチ(取引所)
スイッチの機能は、主にメッセージを受信し、キューをバインドするために転送するために、ACKモードの後にメッセージが格納されていないスイッチは、キューを見つけることができないスイッチはエラーを返し、有効になっています。スイッチは、4つのタイプがあります。直接、トピック、ヘッダーとファンアウトを

ダイレクト:行動の直接的なタイプはrouting_keyメッセージが一致したときに結合routing_keyに設定されている「最初に一致し、配達が」交換体に結合キューに配信されます..です
トピック:プレスメッセージ(最も柔軟)に転送するルール
セットのヘッダ属性パラメータ型スイッチ:ヘッダー
ファンアウトを:結合すべてのキューにメッセージを転送
ダイレクトに交換を
交換RabbitMQのは、デフォルトのモードスイッチでダイレクト、キューのフルテキストを検索するためのキーマッチによると、最も簡単なモードです。

画像

最初のX - Q1結合キー名はオレンジであり; X - Q2は、二つの結合キー、黒と緑の名前を持っています。キーと結合キーに対応するメッセージをルーティングするとき、そのメッセージはキューに知っています。

シモンズ:なぜX Q2ないラインで、まだ、それ、黒、緑、2 Geの結合キーを持っていますか? - これが黒、およびQ2を受け入れQ3、およびQ3のみ情報は、情報だけでなく、黒を受信することができるだけでなく、緑の情報を受信する主な理由です。

トピック所

トピック取引所は、メッセージが主にワイルドカードに基づいて転送します。このスイッチでは、スイッチは、キューに結合され、ルーティングパターンを定義し、次に、キースイッチと一致するメッセージを転送することができ、このようなワイルドカードルーティングモードとの間の経路が必要です。

このモードスイッチで:

ルーティングキーは、文字列(。)などの期間によって分離されなければならないhttp://agreements.us、またはそうでagreements.eu.stockholmと。
ルーティングモードは、アスタリスク(含まなければならないなど)、指定された場所と一致するキーワードのための主要なルートを、この:. Agreements..bようなルートパターンは、それが唯一のルーティング一致させることができ、キーは次のようです:最初のワードは、第四のワードBが契約です。ポンド記号(#)は、例えば、パターンマッチングがagreements.eu.berlinである、1つまたは複数の単語と同等のものを示している。#、そして可能であるagreements.eu.berlinルーティングキーの先頭に。
最初のパラメータはスイッチを表しているように、特定のコードが送信されると、第2のパラメータは、ルーティングキー、すなわち、第3のパラメータメッセージを表します。次のように:
rabbitTemplate.convertAndSend(「testTopicExchange」、「key1.ackey2を」、「!これはRabbitMQの」);
トピックなどを指示は、マッチングの唯一の「パターン」をサポートし、routing_key形で「点線」を使用することができます2つのワイルドカード:

  • それは言葉を表し
  • ゼロ以上の単語を表す
    交換ヘッダー
    ヘッダーが固定routing_keyトピックの直接使用に規則に従ってマッチ、及び比較され、ルールタイプと一致するヘッダが結合キュースイッチにカスタムであり、それは設定されますキーと値のペアルールは、メッセージはまた、キーと値のペア、または試合の全てのペアのようなキーと値のペア(ヘッダ属性)を含み、メッセージは、対応するキューに配信されます。

ファンアウト交換

ファンアウトExchangeメッセージ放送モードに構成routing_keyが無視される場合は、関係なく、ルーティングまたはルーティングモードキーの、送信されたメッセージは、それにすべてのキューをバインドします。

springboot統合のRabbitMQ
あなたは、単に非常に少ない設定を使用する場合springboot統合RabbitMQのは、非常にシンプルで、springbootは、メッセージのさまざまなspringboot-スタータAMQPプロジェクトのサポートを提供します。

使用するのは簡単

1、POM構成パッケージは、主に支持スプリングブートスタータAMQPを追加します

1 
2
3
4
<依存性> 
<のgroupId> org.springframework.boot </のgroupId>
<たartifactId>ばねブートスタータAMQP </たartifactId>
</依存>

2、設定ファイル

RabbitMQのインストールアドレス、ポート、およびアカウント情報を設定します

1 
2
3
4
5
6
spring.application.name = spirng-ブートのRabbitMQ

spring.rabbitmq.host = 127.0.0.1
spring.rabbitmq.port = 5672
spring.rabbitmq.username =ゲスト
spring.rabbitmq.password =ゲスト
キュー構成
1 
2
3
4
5
6
7
8
9
@Configuration 
パブリッククラスRabbitConfig {

@Bean
パブリックキューキュー(){
(「こんにちは」)新しいキューを返します。
}

}

送信者

1 
2
3
4
5
6
7
8
9
10
11
12
13
14
rabbitTemplateはspringbootを提供するデフォルトの実装であります

パブリッククラスHelloSender {

@Autowired
プライベートAmqpTemplate rabbitTemplate。

ます。public voidセンド(){
文字列のコンテキスト= "こんにちは" +新しいDate();
System.out.println( "送信者:" +コンテキスト);
this.rabbitTemplate.convertAndSend( "ハロー"、コンテキスト)。
}

}

受信者

1
2
3
4
5
6
7
8
9
10
@Component
@RabbitListener(queues = "hello")
public class HelloReceiver {

@RabbitHandler
public void process(String hello) {
System.out.println("Receiver : " + hello);
}

}

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
@RunWith(SpringRunner.class)
@SpringBootTest
public class RabbitMqHelloTest {

@Autowired
private HelloSender helloSender;

@Test
public void hello() throws Exception {
helloSender.send();
}

}

注意,发送者和接收者的queue name必须一致,不然不能接收
多对多使用

一个发送者,N个接收者或者N个发送者和N个接收者会出现什么情况呢?

一对多发送

对上面的代码进行了小改造,接收端注册了两个Receiver,Receiver1和Receiver2,发送端加入参数计数,接收端打印接收到的参数,下面是测试代码,发送一百条消息,来观察两个接收端的执行效果。

1
2
3
4
5
6
@Test
public void oneToMany() throws Exception {
for (int i=0;i<100;i++){
neoSender.send(i);
}
}

结果如下:

1
2
3
4
5
6
7
8
9
10
Receiver 1: spirng boot neo queue ****** 11
Receiver 2: spirng boot neo queue ****** 12
Receiver 2: spirng boot neo queue ****** 14
Receiver 1: spirng boot neo queue ****** 13
Receiver 2: spirng boot neo queue ****** 15
Receiver 1: spirng boot neo queue ****** 16
Receiver 1: spirng boot neo queue ****** 18
Receiver 2: spirng boot neo queue ****** 17
Receiver 2: spirng boot neo queue ****** 19
Receiver 1: spirng boot neo queue ****** 20

根据返回结果得到以下结论 > 一个发送者,N个接受者,经过测试会均匀的将消息发送到N个接收者中

多对多发送

复制了一份发送者,加入标记,在一百个循环中相互交替发送

1
2
3
4
5
6
7
@Test
public void manyToMany() throws Exception {
for (int i=0;i<100;i++){
neoSender.send(i);
neoSender2.send(i);
}
}

结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
Receiver 1: spirng boot neo queue ****** 20
Receiver 2: spirng boot neo queue ****** 20
Receiver 1: spirng boot neo queue ****** 21
Receiver 2: spirng boot neo queue ****** 21
Receiver 1: spirng boot neo queue ****** 22
Receiver 2: spirng boot neo queue ****** 22
Receiver 1: spirng boot neo queue ****** 23
Receiver 2: spirng boot neo queue ****** 23
Receiver 1: spirng boot neo queue ****** 24
Receiver 2: spirng boot neo queue ****** 24
Receiver 1: spirng boot neo queue ****** 25
Receiver 2: spirng boot neo queue ****** 25

结论:和一对多一样,接收端仍然会均匀接收到消息
高级使用

对象的支持

springboot以及完美的支持对象的发送和接收,不需要格外的配置。

//发送者

1
2
3
4
public void send(User user) {
System.out.println("Sender object: " + user.toString());
this.rabbitTemplate.convertAndSend("object", user);
}

//接受者

1
2
3
4
@RabbitHandler
public void process(User user) {
System.out.println("Receiver object : " + user);
}

结果如下:

1
2
Sender object: User{name='neo', pass='123456'}
Receiver object : User{name='neo', pass='123456'}

Topic Exchange

topic 是RabbitMQ中最灵活的一种方式,可以根据routing_key自由的绑定不同的队列

首先对topic规则配置,这里使用两个队列来测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Configuration
public class TopicRabbitConfig {

final static String message = "topic.message";
final static String messages = "topic.messages";

@Bean
public Queue queueMessage() {
return new Queue(TopicRabbitConfig.message);
}

@Bean
public Queue queueMessages() {
return new Queue(TopicRabbitConfig.messages);
}

@Bean
TopicExchange exchange() {
return new TopicExchange("exchange");
}

@Bean
Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {
return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");
}

@Bean
Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) {
return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");
}
}

使用queueMessages同时匹配两个队列,queueMessage只匹配”topic.message”队列

1
2
3
4
5
6
7
8
9
10
11
public void send1() {
String context = "hi, i am message 1";
System.out.println("Sender : " + context);
this.rabbitTemplate.convertAndSend("exchange", "topic.message", context);
}

public void send2() {
String context = "hi, i am messages 2";
System.out.println("Sender : " + context);
this.rabbitTemplate.convertAndSend("exchange", "topic.messages", context);
}

发送send1会匹配到topic.#和topic.message 两个Receiver都可以收到消息,发送send2只有topic.#可以匹配所有只有Receiver2监听到消息

Fanout Exchange

Fanout 就是我们熟悉的广播模式或者订阅模式,给Fanout交换机发送消息,绑定了这个交换机的所有队列都收到这个消息。

Fanout 相关配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@Configuration
public class FanoutRabbitConfig {

@Bean
public Queue AMessage() {
return new Queue("fanout.A");
}

@Bean
public Queue BMessage() {
return new Queue("fanout.B");
}

@Bean
public Queue CMessage() {
return new Queue("fanout.C");
}

@Bean
FanoutExchange fanoutExchange() {
return new FanoutExchange("fanoutExchange");
}

@Bean
Binding bindingExchangeA(Queue AMessage,FanoutExchange fanoutExchange) {
return BindingBuilder.bind(AMessage).to(fanoutExchange);
}

@Bean
Binding bindingExchangeB(Queue BMessage, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(BMessage).to(fanoutExchange);
}

@Bean
Binding bindingExchangeC(Queue CMessage, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(CMessage).to(fanoutExchange);
}

}

这里使用了A、B、C三个队列绑定到Fanout交换机上面,发送端的routing_key写任何字符都会被忽略:

1
2
3
4
5
public void send() {
String context = "hi, fanout msg ";
System.out.println("Sender : " + context);
this.rabbitTemplate.convertAndSend("fanoutExchange","", context);
}

结果如下:

结果说明,绑定到fanout交换机上面的队列都收到了消息

消息持久化

在生产环境中,我们需要考虑万一生产者挂了,消费者挂了,或者 rabbitmq 挂了怎么样。一般来说,如果生产者挂了或者消费者挂了,其实是没有影响,因为消息就在队列里面。那么万一 rabbitmq 挂了,之前在队列里面的消息怎么办,其实可以做消息持久化,RabbitMQ 会把信息保存在磁盘上。

做法是可以先从 Connection 对象中拿到一个 Channel 信道对象,然后再可以通过该对象设置 消息持久化。

プロデューサまたはコンシューマの再接続
ここでは、自動再接続メカニズムを春。

ACK応答メカニズム

各消費者は、受信したデータを処理するためにいくつかの時間がかかることがあります。プロセスであれば、消費者の間違った、異常終了し、データ処理が完了していないので、残念ながら、このデータは失われます。一方、我々は無ACK方法を使用しないため、すなわち消費者のデータを受信した後、それぞれの時間を確認するために、かかわらず、処理が完了しているかどうかの、RabbitMQのサーバーはすぐにこのメッセージが完了としてマークされ、その後、キューから削除置きます。

消費者が予期せず終了し、このときのデータは失われていないように、そのデータは、さらに消費者のプロセスを処理することができた場合(これが事実であることに注意してください)。
そのデータが失われないようにするために、RabbitMQのは、その確認応答メッセージ確認メカニズムをサポートしています。データを正しく処理できるだけではなく、消費者が受信されていることを確実にするために、我々は何の-ACKを使用することはできません。ACKが、データが処理された後に送信されるべきです。

Ackを処理し、RabbitMQのデータが受信されている伝えることで、データを処理した後送信し、RabbitMQのは、安全に削除する行くことができます。
消費者が撤退したがACKを送信しなかった場合は、RabbitMQのは、次の消費者にこのメッセージを送信します。これは、データが消費者異常終了した場合に失われないことを保証します。

質問があれば、ACK機構にこちらをクリックしてください:https://www.zhihu.com/question/41976893

オリジナル:ビッグボックス  Springboot統合RabbitMp


おすすめ

転載: www.cnblogs.com/petewell/p/11422306.html