序文
詳細1. SpringBoot統合の設定
-
リスナーを達成するために、パブリッシャ-確認、我々はに戻るブローカ最後に確認要求をリッスン:
RabbitTemplate.ConfirmCallback
-
エンド・ブローカーメッセージを確実にするために、パブリッシャ-戻り、ルーティングキーが到達不能に表示された場合は、成功を確実にするために、後続の処理のためのリスナー到達不能メッセージ、メッセージのルーティングを使用して、到達可能です:
RabbitTemplate.ReturnCallback
なお、コンフィギュレーションテンプレートの必須の効率的な生産を確実にするために聞くためにメッセージを送信するとき=真のエンドはまた、等送信リトライ、タイムアウト、数、間隔、等の他の特性を構成することができます
2.コードを示してい
2.1生産終了
2.1.1新規プロジェクトspringbootプロデューサー
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cp</groupId>
<artifactId>springboot-producer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot-producer</name>
<description>springboot-producer</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
复制代码
RabbitSender.javaニュースプロデューサー
@Component
public class RabbitSender {
//自动注入RabbitTemplate模板类
@Autowired
private RabbitTemplate rabbitTemplate;
//回调函数: confirm确认
final ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
System.err.println("correlationData: " + correlationData);
System.err.println("ack: " + ack);
if(!ack){
//可以进行日志记录、异常处理、补偿处理等
System.err.println("异常处理....");
}else {
//更新数据库,可靠性投递机制
}
}
};
//回调函数: return返回
final ReturnCallback returnCallback = new RabbitTemplate.ReturnCallback() {
@Override
public void returnedMessage(org.springframework.amqp.core.Message message, int replyCode, String replyText,
String exchange, String routingKey) {
System.err.println("return exchange: " + exchange + ", routingKey: "
+ routingKey + ", replyCode: " + replyCode + ", replyText: " + replyText);
}
};
//发送消息方法调用: 构建Message消息
public void send(Object message, Map<String, Object> properties) throws Exception {
MessageHeaders mhs = new MessageHeaders(properties);
Message msg = MessageBuilder.createMessage(message, mhs);
rabbitTemplate.setConfirmCallback(confirmCallback);
rabbitTemplate.setReturnCallback(returnCallback);
//id + 时间戳 全局唯一 用于ack保证唯一一条消息,这边做测试写死一个。但是在做补偿策略的时候,必须保证这是全局唯一的消息
CorrelationData correlationData = new CorrelationData("1234567890");
rabbitTemplate.convertAndSend("exchange-1", "springboot.abc", msg, correlationData);
}
}
复制代码
application.properties
spring.rabbitmq.addresses=localhost:5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/vhost_cp
spring.rabbitmq.connection-timeout=15000
spring.rabbitmq.publisher-confirms=true
spring.rabbitmq.publisher-returns=true
spring.rabbitmq.template.mandatory=true
复制代码
2.1.2操作制御局
取引所を追加
キューを追加
バインディング所キュー
routingKeyを変更し、springbootは春に変更し、メソッドを入力することreturnCallbackです
今回はエラーを検出しました
correlationData: CorrelationData [id=1234567890]
ack: false
异常处理....
复制代码
偽2.1.3の問題を解決するために、ACK
我々はテストメソッドの終わりには、RabbitMQの関連リソースも閉じられた試験方法で試験するので、私たちのメッセージ出ますが、非同期ConfirmCallbackが原因リソースと上記の問題の出現に閉鎖されたが、これは、あります。Thread.sleep()を解決することができる参加。
@Test
public void testSender1() throws Exception {
Map<String, Object> properties = new HashMap<>();
properties.put("number", "12345");
properties.put("send_time", simpleDateFormat.format(new Date()));
rabbitSender.send("Hello RabbitMQ For Spring Boot!", properties);
Thread.sleep(2000);
}
复制代码
2.2消費者エンド
コア消費者側の設定:
= 5 spring.rabbitmq.listener.simple最大10、デフォルト5 spring.rabbitmq.listener.simple.concurrency: - モード##サイン手動符号spring.rabbitmq.listener.simple.acknowledge-モード=手動##は、モニタを制限するために設けられています。最大同時実行性= 10
-
私たちは、メッセージ配信の信頼性を保証できるように、消費者がキューを返すことに失敗したときに手動で最初に確認応答モードを設定し、手動処理のためのACKは、その後、消費者またはエンドのようなプロセスのトラフィックログによると、(推奨されません)に行うことができます。
-
あなたは例消費者側の同時モニタリングのために、リスナーの数と消費者側の最大数を設定することができます
@RabbitListenerの使用注釈
- 非常に使いやすい。このために実用的な作品で、ノート@RabbitListener消費者エンドモニタ
- @RabbitListener注釈は注釈を構成することができる組み合わせであります
- 取引所@ @ QueueBinding、@キュー、直接ノートのこの組み合わせによってように一回の消費者サイドスイッチ、キュー、結合、ルーティング、および構成監視機能を取得し、します。
例えば、この方法でのonMessage @RabbitListenerは、注釈を追加し、また、あなたが他のコメント@RabbitHandlerを追加する必要があり、コードは、消費者に聞いています。
Exchangeの種類を設定し、永続場合、Exchange値に設定され、キューに書かれた、結合を確立し、式が真とルーティングキーに設定されています。この単純な方法では、複雑なコードのロジックの前に完了することができます。一方、構成ファイル、ダイナミックアクセスに設定をお勧めします。など該当するMQキュー、Exchangeは、存在しない場合、彼らはまた、注釈文を作成することができ、あなたは自分自身をテストすることができます!
2.2.1新規プロジェクトspringboot、消費者
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cp</groupId>
<artifactId>springboot-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot-consumer</name>
<description>springboot-consumer</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
复制代码
RabbitReceiver.javaニュースプロデューサー
@Component
public class RabbitReceiver {
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "queue-1",
durable="true"),
exchange = @Exchange(value = "exchange-1",
durable="true",
type= "topic",
ignoreDeclarationExceptions = "true"),
key = "springboot.*"
)
)
@RabbitHandler
public void onMessage(Message message, Channel channel) throws Exception {
System.err.println("--------------------------------------");
System.err.println("消费端Payload: " + message.getPayload());
Long deliveryTag = (Long)message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
//手工ACK,获取deliveryTag
channel.basicAck(deliveryTag, false);
}
}
复制代码
application.properties
spring.rabbitmq.addresses=localhost:5672
spring.rabbitmq.username=user_cp
spring.rabbitmq.password=123456
spring.rabbitmq.virtual-host=/vhost_cp
spring.rabbitmq.connection-timeout=15000
spring.rabbitmq.listener.simple.acknowledge-mode=manual
spring.rabbitmq.listener.simple.concurrency=5
spring.rabbitmq.listener.simple.max-concurrency=10
复制代码
消費者がすることができるかどうか、生産終了に送信された以前のメッセージを参照して、アプリケーションを実行します。
印刷結果
ここでは非常に多く存在しているとき、私は消費者のため、複数のメッセージをテストする前にいるので。3.最適化されたコード
- カスタムJavaオブジェクトのメッセージ
- 動的構成に@RabbitListener注釈構成
@Payload:特定のメッセージ本体のボディを指定します。 @Headers:ヘッダを取得します。
3.1消費者エンドの最適化
1、最初のターゲットの順序を定義します
public class Order implements Serializable {
private String id;
private String name;
public Order() {
}
public Order(String id, String name) {
super();
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
复制代码
注意:我々は、オブジェクトを転送し、それをシリアル化する必要があります。それ以外の場合は送信が失敗します。
2、RabbitReceiverは、リスナーを追加します
/**
*
* spring.rabbitmq.listener.order.queue.name=queue-2
spring.rabbitmq.listener.order.queue.durable=true
spring.rabbitmq.listener.order.exchange.name=exchange-2
spring.rabbitmq.listener.order.exchange.durable=true
spring.rabbitmq.listener.order.exchange.type=topic
spring.rabbitmq.listener.order.exchange.ignoreDeclarationExceptions=true
spring.rabbitmq.listener.order.key=springboot.*
* @param order
* @param channel
* @param headers
* @throws Exception
*/
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "${spring.rabbitmq.listener.order.queue.name}",
durable="${spring.rabbitmq.listener.order.queue.durable}"),
exchange = @Exchange(value = "${spring.rabbitmq.listener.order.exchange.name}",
durable="${spring.rabbitmq.listener.order.exchange.durable}",
type= "${spring.rabbitmq.listener.order.exchange.type}",
ignoreDeclarationExceptions = "${spring.rabbitmq.listener.order.exchange.ignoreDeclarationExceptions}"),
key = "${spring.rabbitmq.listener.order.key}"
)
)
@RabbitHandler
public void onOrderMessage(@Payload com.cp.springboot.entity.Order order,
Channel channel,
@Headers Map<String, Object> headers) throws Exception {
System.err.println("--------------------------------------");
System.err.println("消费端order: " + order.getId());
Long deliveryTag = (Long)headers.get(AmqpHeaders.DELIVERY_TAG);
//手工ACK
channel.basicAck(deliveryTag, false);
}
复制代码
それは、application.properties構成に動的な獲得を書いています。当社はまた、コンフィギュレーション・センターにそれらを置くように、好きなことができます。たとえば、次のようにCtripのオープンソースのコンフィグレーションセンターアポロ
3、application.properties
spring.rabbitmq.listener.order.queue.name=queue-2
spring.rabbitmq.listener.order.queue.durable=true
spring.rabbitmq.listener.order.exchange.name=exchange-2
spring.rabbitmq.listener.order.exchange.durable=true
spring.rabbitmq.listener.order.exchange.type=topic
spring.rabbitmq.listener.order.exchange.ignoreDeclarationExceptions=true
spring.rabbitmq.listener.order.key=springboot.*
复制代码
3.2生産終了の最適化
1は、それはまた、Orderオブジェクトである消費者側との一貫性を保つ必要があります。
2、RabbitSenderは、メッセージを送信するために添加しました
//发送消息方法调用: 构建自定义对象消息
public void sendOrder(Order order) throws Exception {
rabbitTemplate.setConfirmCallback(confirmCallback);
rabbitTemplate.setReturnCallback(returnCallback);
//id + 时间戳 全局唯一
CorrelationData correlationData = new CorrelationData("0987654321");
rabbitTemplate.convertAndSend("exchange-2", "springboot.def", order, correlationData);
}
复制代码
3、試験方法を追加
@Test
public void testSender2() throws Exception {
Order order = new Order("001", "第一个订单");
rabbitSender.sendOrder(order);
//防止资源提前关闭,ConfirmCallback异步回调失败
Thread.sleep(2000);
}
复制代码
3.3試験
testSender2()メソッドを実行します。
エンド印刷物制作のニュース
消費者側の印刷メッセージ
これまでのところ、完成RabbitMQの統合SpringBootは、実際には、シナリオの使用がほぼ同じです。
文末
個人的なマイクロチャネル公衆番号へようこそ注意:Coderのプログラムの最新オリジナルな技術に関する記事と無料の学習教材のため、多くのブティックマインドマップ、インタビューデータ、PMPの準備資料あなたがリードするために、待っているあなたは、いつでも、どこでも技術的な知識を習得することができます!QQのグループを作成します:315 211 365を、私たちは一緒にグループ交換研究に歓迎します。ありがとうございます!また、必要としている友人の側に導入することができます。
記事のGithubに含ま:github.com/CoderMerlin ... Gitee:gitee.com/573059382/c ...歓迎の注意と星〜
参考記事:
「簡潔RabbitMQのメッセージング・ミドルウェア」
推奨読書:
すべてここメッセージングミドルウェア--RabbitMQ(7)高度な機能!(オン)