1.什麼是消息驅動
SpringCloud Stream消息驅動可以簡化開發人員對消息中間件的使用複雜度,讓系統開發人員更多盡力專注與核心業務邏輯的開發。SpringCloud Stream基於SpringBoot實現,自動配置化的功能可以幫助我們快速上手學習,類似與我們之前學習的orm框架,可以平滑的切換多種不同的數據庫。
目前SpringCloud Stream 目前只支持 rabbitMQ和kafka
2.消息驅動原理
綁定器
通過定義綁定器作爲中間層,實現了應用程序與消息中間件細節之間的隔離。通過嚮應用程序暴露統一的Channel通過,是的應用程序不需要再考慮各種不同的消息中間件的實現。當需要升級消息中間件,或者是更換其他消息中間件產品時,我們需要做的就是更換對應的Binder綁定器而不需要修改任何應用邏輯 。
在該模型圖上有如下幾個核心概念:
• Source: 當需要發送消息時,我們就需要通過Source,Source將會把我們所要發送的消息(POJO對象)進行序列化(默認轉換成JSON格式字符串),然後將這些數據發送到Channel中;
• Sink: 當我們需要監聽消息時就需要通過Sink來,Sink負責從消息通道中獲取消息,並將消息反序列化成消息對象(POJO對象),然後交給具體的消息監聽處理進行業務處理;
• Channel: 消息通道是Stream的抽象之一。通常我們向消息中間件發送消息或者監聽消息時需要指定主題(Topic)/消息隊列名稱,但這樣一旦我們需要變更主題名稱的時候需要修改消息發送或者消息監聽的代碼,但是通過Channel抽象,我們的業務代碼只需要對Channel就可以了,具體這個Channel對應的是那個主題,就可以在配置文件中來指定,這樣當主題變更的時候我們就不用對代碼做任何修改,從而實現了與具體消息中間件的解耦;
• Binder: Stream中另外一個抽象層。通過不同的Binder可以實現與不同消息中間件的整合,比如上面的示例我們所使用的就是針對Kafka的Binder,通過Binder提供統一的消息收發接口,從而使得我們可以根據實際需要部署不同的消息中間件,或者根據實際生產中所部署的消息中間件來調整我們的配置。
。
3.SpringCloud-Stream創建生產者
依賴
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencies>
<!-- SpringBoot整合Web組件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- springcloud stream 就是對springboot 整合 rabbit mq 在做了一層封裝 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
</dependencies>
</project>
配置文件
server:
port: 9000
spring:
application:
name: spingcloud-stream-producer
#####默認是本地配置
# rabbitmq:
# host: 127.0.0.1
# port: 5672
# username: guest
# password: guest
創建發送通道的接口
// 創建 發送消息通道
public interface SendMessageInterface {
// 1.創建發送消息通道,
@Output("my_stream_channel")
SubscribableChannel sendMsg();
}
controller
@RestController
public class SendMsgController {
@Autowired
private SendMessageInterface sendMessageInterface;
// 生產者流程:
// 1.創建發送消息通道
// 2.生產投遞消息(生產者往通道中發送消息)
@RequestMapping("/sendMsg")
public String sendMsg() {
String msg = UUID.randomUUID().toString();
System.out.println("生產者發送內容msg:" + msg);
Message build = MessageBuilder.withPayload(msg.getBytes()).build();
sendMessageInterface.sendMsg().send(build);
return "success";
}
// 3.開啓綁定(結合)
}
啓動類
@SpringBootApplication
@EnableBinding(SendMessageInterface.class)
public class AppProducer {
public static void main(String[] args) {
SpringApplication.run(AppProducer.class, args);
}
// 思考: 在rabbit 有交換機 隊列
// 默認以通道名稱 創建交換機,消費者啓動的時候 隨機創建一個隊列名稱
}
4.SpringCloud-Stream創建消費者
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencies>
<!-- SpringBoot整合Web組件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- springcloud stream 就是對springboot 整合 rabbit mq 在做了一層封裝 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
</dependencies>
</project>
配置文件
server:
port: 8002
spring:
application:
name: spring-cloud-stream
# rabbitmq:
# host: 192.168.174.128
# port: 5672
# username: guest
# password: guest
cloud:
stream:
bindings:
my_stream_channel: ###指定 管道名稱
#指定該應用實例屬於 stream 消費組
group: stream
定義消費者
@Component
public class Consumer {
@Value("${server.port}")
private String serverPort;
@StreamListener("my_stream_channel")
public void redMsg(String msg) {
System.out.println("消費者獲取到生產者投遞的消息:" + msg + ",端口號:" + serverPort);
}
}
public interface RedMsgInterface {
@Input("my_stream_channel")
SubscribableChannel redMsg();
}
啓動類
@SpringBootApplication
@EnableBinding(RedMsgInterface.class)
public class AppConsumer {
public static void main(String[] args) {
SpringApplication.run(AppConsumer.class, args);
}
// 消費者隊列 底層自動創建一個隊列 綁定my_stream_channel
}
可以看到,我們上面並創建隊列,而是他自動幫我創建的
5.更改環境爲kafka
Maven依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-kafka</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
生產者配置
server:
port: 9000
spring:
cloud:
stream:
# 設置成使用kafka
kafka:
binder:
# Kafka的服務端列表,默認localhost
brokers: 192.168.212.174:9092,192.168.212.175:9092,192.168.212.176:9092
# Kafka服務端連接的ZooKeeper節點列表,默認localhost
zkNodes: 192.168.212.174:2181,192.168.212.175:2181,192.168.212.176:2181
minPartitionCount: 1
autoCreateTopics: true
autoAddPartitions: true
消費者配置
server:
port: 8000
spring:
application:
name: springcloud_kafka_consumer
cloud:
instance-count: 1
instance-index: 0
stream:
kafka:
binder:
brokers: 192.168.212.174:9092,192.168.212.175:9092,192.168.212.176:9092
zk-nodes: 192.168.212.174:2181,192.168.212.175:2181,192.168.212.176:2181
auto-add-partitions: true
auto-create-topics: true
min-partition-count: 1
bindings:
input:
destination: my_msg
group: s1
consumer:
autoCommitOffset: false
concurrency: 1
partitioned: false