RocketMQ
一. JMS介紹
JMS(Java Message Service),是Java平臺中關於面向消息中間件的接口,是一種與廠商無關的API,用來訪問消息收發。它的使用場景如下:
- 實現業務的解耦、削峯,異步。
- 跨平臺,多語言
- 分佈式事務,最終一致性
二. RocketMQ常見的概念
Producer:生產消息的服務。
Producer Group: 消息生產者組,發送同類消息的一個消息生產組。
Consumer: 消費消息的服務。
Consumber Group: 消費同類消息的多個實例。
Topic: 主題,某類消息,queue是消息的物理管理單位,而topic是邏輯管理單位,一個topic下有多個queue,默 認4個。
Tag: 標籤,子主題(二級分類),對Topic的進一步細化,用於區分同個主題下不同的業務消息。
Message: 消息,每個message必須指定一個topic
Broker: MQ程序,接收生產的消息,提供給消費者的程序。
Name Server: 給生產者和消費者提供路由信息,提供輕量級的服務發現、路由、元數據信息
Offset: 偏移量,可以理解爲消息進度
Commit log: 消息存儲會寫在 commit log文件中
三. RocketMQ的使用
RocketMQ的下載地址:http://rocketmq.apache.org/release_notes/release-notes-4.4.0/
3.1 啓動
rocketmq是用純粹的Java語言編寫,所以首先需要安裝Jdk.
- windows系統下啓動:先啓動mqnamesrv.cmd, 然後再啓動mqbroker.cmd -n localhost:9876
- Linux操作系統下啓動:先啓動mqnamesrv.sh, 然後再啓動mqbroker.sh -n localhost:9876
3.2 驗證
windows環境下:
set NAMESRV_ADDR=localhost:9876
tools.cmd org.apache.rocketmq.example.quickstart.Producer
set NAMESRV_ADDR=localhost:9876
tools.cmd org.apache.rocketmq.example.quickstart.Consumer
Linux環境下:
export NAMESRV_ADDR=localhost:9876
bin/tools.sh org.apache.rocketmq.example.quickstart.Producer
export NAMESRV_ADDR=localhost:9876
bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer
3.3 rocketmq可視化控制檯安裝
下載地址:https://github.com/apache/rocketmq-externals
進入到 rocketmq-console 文件夾下,執行如下命令:
mvn clean package -Dmaven.test.skip=true
java -jar target/rocketmq-console-ng-1.0.1.jar
在瀏覽器輸入:http://localhost:8080進行訪問。
四. RocketMQ整合Spring boot
4.1 依賴
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
4.2 配置
新建一個mq.properties文件,文件的內容如下:
主要就是將基本參數放在了配置文件中,直接在類中調用使用
nameServerAdr=localhost:9876
producerGroupName=producer-test
sendMailTopic=email-send-topic
sendMailTopic.tag=registerSuccess
consumerGroup=consumer-group
4.3 生產者類的編寫
// 消息生產者
@Configuration
@PropertySource("classpath:mq.properties") //制定properties文件的位置
public class RocketProducer {
@Value("${nameServerAdr}")
private String nameServerAddress; // name-server的地址
@Value("${producerGroupName}")
private String producerGroup; //生產者組名
@Value("${sendMailTopic}")
private String topic;
@Value("${sendMailTopic.tag}")
private String tag;
@Bean
public DefaultMQProducer defaultMqProducer() {
// 實例消息的生產者,然後通過構造方法制定其組
DefaultMQProducer defaultMQProducer = new DefaultMQProducer(this.producerGroup);
//設置nameServer的地址
defaultMQProducer.setNamesrvAddr(this.nameServerAddress);
try {
defaultMQProducer.start(); //啓動producer
} catch (MQClientException e) {
e.printStackTrace();
}
return defaultMQProducer;
}
}
我們在Controller中調用創建消息
@RequestMapping("/test01")
public Object test(){
DefaultMQProducer defaultMQProducer = rocketProducer.defaultMqProducer();
for (int i = 0; i < 100; i++) {
//創建信息類
Message msg = null;
try {
//參數 發送消息主題名, 消息標籤, 信息
msg = new Message("toipcTest",
"aaaa",
("你好呀RocketMq " + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
SendResult sendResult = defaultMQProducer.send(msg);
System.out.printf("%s%n", sendResult);
} catch (UnsupportedEncodingException e) {
System.out.println(e.getMessage());
} catch (InterruptedException | RemotingException | MQBrokerException | MQClientException e) {
e.printStackTrace();
}
}
return "ok";
}
4.4 消費者類的編寫
@Configuration
@PropertySource("classpath:mq.properties")
public class RocketConsumer {
@Value("${nameServerAdr}")
private String nameServerAddress; // name-server的地址
@Value("${producerGroupName}")
private String producerGroup; //生產者組名
@Value("${sendMailTopic}")
private String topic;
@Value("${sendMailTopic.tag}")
private String tag;
@Bean
public DefaultMQPushConsumer defaultMQPushConsumer() throws MQClientException {
// 實例消息的生產者,然後通過構造方法制定其組
DefaultMQPushConsumer defaultMqPushConsumer = new DefaultMQPushConsumer();
defaultMqPushConsumer.setConsumerGroup(this.producerGroup);
defaultMqPushConsumer.setNamesrvAddr(this.nameServerAddress);
//設置nameServer的地址
defaultMqPushConsumer.subscribe("toipcTest","aaaa");
defaultMqPushConsumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
System.out.println("開始接受消息==========================");
msgs.forEach(mt -> {
System.out.println(new String(mt.getBody()));
});
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
defaultMqPushConsumer.start();
return defaultMqPushConsumer;
}
結果
消息成功接收到了