封面圖:渤海大學,遼寧省錦州,2012年6月。
RocketMQ 是阿里巴巴於2012年開源的分佈式消息中間件,後來捐贈給Apache軟件基金會,並於 2017 年9月25日成爲 Apache 的頂級項目。別的就不多說了,文末附有參考資料,可以學習使用,直接奉上代碼。
測試環境是兩臺服務器搭建的雙Master集羣。
源代碼
https://github.com/wu-boy/spring-boot-demo
jms模塊下的rocketmq模塊。
RocketMQ依賴
在Spring Boot項目中,可以使用RocketMQ的外部項目rocketmq-spring-boot-starter來方便集成。
源碼地址:https://github.com/apache/rocketmq-spring,裏面還有例子可供參考。
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.0.4</version>
</dependency>
配置文件
rocketmq:
name-server: ip:port;ip:port
producer:
group: producer_group_test
global-config:
topic-string: topic_string
topic-user: topic_user
string-consumer-group: string_consumer_group
user-consumer-group: user_consumer_group
name-server配置的是RocketMQ集羣,有幾個服務器就配置幾個IP地址和端口,IP和端口之間用分號隔開。
配置類
@Component
@ConfigurationProperties("global-config")
public class GlobalConfig {
/**
* 字符串主題
*/
private String topicString;
/**
* 用戶主題
*/
private String topicUser;
/**
* 字符串消費者組
*/
private String stringConsumerGroup;
/**
* 用戶消費者組
*/
private String userConsumerGroup;
// 請自行補充get/set
}
實體類User
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
private String username;
// 請自行補充get/set
}
字符串消費者
@Service
@RocketMQMessageListener(consumerGroup = "${global-config.string-consumer-group}", topic = "${global-config.topic-string}")
public class StringConsumer implements RocketMQListener<String> {
private Logger log = LoggerFactory.getLogger(this.getClass());
@Override
public void onMessage(String message) {
log.info("消費字符串消息{}", message);
}
}
User消費者
@Service
@RocketMQMessageListener(consumerGroup = "${global-config.user-consumer-group}", topic = "${global-config.topic-user}")
public class UserConsumer implements RocketMQListener<User> {
private Logger log = LoggerFactory.getLogger(this.getClass());
@Override
public void onMessage(User user) {
log.info("消費用戶消息{}", user.getUsername());
}
}
創建RocketmqController進行測試
@RestController
@RequestMapping("rocketmq")
public class RocketmqController {
private Logger log = LoggerFactory.getLogger(this.getClass());
@Autowired
private GlobalConfig globalConfig;
@Resource
private RocketMQTemplate rocketMQTemplate;
/**
* 同步發送
* 頁面訪問http://localhost:8080/rocketmq/sync
* @throws Exception
*/
@GetMapping("sync")
public void sync(){
SendResult sendResult = rocketMQTemplate.syncSend(globalConfig.getTopicString(), "Hello world!");
log.info("同步發送字符串{}, 發送結果{}", globalConfig.getTopicString(), sendResult);
User user = new User();
user.setId("1");
user.setUsername("wusq");
sendResult = rocketMQTemplate.syncSend(globalConfig.getTopicUser(), user);
log.info("同步發送對象{}, 發送結果{}", globalConfig.getTopicUser(), sendResult);
}
/**
* 異步發送
* 頁面訪問http://localhost:8080/rocketmq/async
* @throws Exception
*/
@GetMapping("async")
public void async(){
rocketMQTemplate.asyncSend(globalConfig.getTopicString(), "Hello world!", new SendCallback() {
@Override
public void onSuccess(SendResult var1) {
log.info("異步發送成功{}", var1);
}
@Override
public void onException(Throwable var1) {
log.info("異步發送失敗{}", var1);
}
});
}
/**
* 單向發送
* 頁面訪問http://localhost:8080/rocketmq/oneway
* @throws Exception
*/
@GetMapping("oneway")
public void oneway(){
rocketMQTemplate.sendOneWay(globalConfig.getTopicString(), "Hello world!");
log.info("單向發送");
}
}
Controller中演示了3種方式發送消息:
- 同步發送
指消息發送方發出數據後,會在接收方發回的響應之後才發送下一個數據包。 - 異步發送
指發送方發出數據後,不等待接收方發回響應,就接着發送下一個數據包。 - 單向發送
指只負責發送消息而不等待服務器迴應且沒有回調函數觸發。
結束語
綜上所述,RocketMQ結合Spring Boot使用,還是比較簡單的。
消費者在消費一條數據的時候如果發生異常,這條數據也不會丟的,消費者會自動重新消費此條數據。
參考資料
《分佈式消息中間件實踐–詳解消息中間件的高可用、高性能配置和原理》,倪偉著。