學(xué)習(xí)完整課程請(qǐng)移步 互聯(lián)網(wǎng) Java 全棧工程師
本節(jié)視頻
概述
RocketMQ 是一款開(kāi)源的分布式消息系統(tǒng)聋亡,基于高可用分布式集群技術(shù)抡砂,提供低延時(shí)的胚迫、高可靠的消息發(fā)布與訂閱服務(wù)。
由于本教程整個(gè)案例基于 Spring Cloud测秸,故我們采用 Spring Cloud Stream 完成一次發(fā)布和訂閱
Spring Cloud Stream
Spring Cloud Stream 是一個(gè)用于構(gòu)建基于消息的微服務(wù)應(yīng)用框架拓售。它基于 Spring Boot 來(lái)創(chuàng)建具有生產(chǎn)級(jí)別的單機(jī) Spring 應(yīng)用瞬浓,并且使用 Spring Integration
與 Broker 進(jìn)行連接惠遏。
Spring Cloud Stream 提供了消息中間件配置的統(tǒng)一抽象,推出了 publish-subscribe
拄养、consumer groups
离斩、partition
這些統(tǒng)一的概念银舱。
Spring Cloud Stream 內(nèi)部有兩個(gè)概念:
- Binder: 跟外部消息中間件集成的組件,用來(lái)創(chuàng)建 Binding跛梗,各消息中間件都有自己的 Binder 實(shí)現(xiàn)寻馏。
- Binding: 包括 Input Binding 和 Output Binding。
Binding 在消息中間件與應(yīng)用程序提供的 Provider 和 Consumer 之間提供了一個(gè)橋梁核偿,實(shí)現(xiàn)了開(kāi)發(fā)者只需使用應(yīng)用程序的 Provider 或 Consumer 生產(chǎn)或消費(fèi)數(shù)據(jù)即可诚欠,屏蔽了開(kāi)發(fā)者與底層消息中間件的接觸。
解決連接超時(shí)問(wèn)題
在之前的 基于 Docker 安裝 RocketMQ 章節(jié)中漾岳,我們采用 Docker 部署了 RocketMQ 服務(wù)轰绵,此時(shí) RocketMQ Broker 暴露的地址和端口(10909,10911)是基于容器的尼荆,會(huì)導(dǎo)致我們開(kāi)發(fā)機(jī)無(wú)法連接左腔,從而引發(fā) org.apache.rocketmq.remoting.exception.RemotingTooMuchRequestException: sendDefaultImpl call timeout
異常
注意下圖中的 IP 地址,這個(gè)是容器的 IP捅儒,開(kāi)發(fā)機(jī)與容器不在一個(gè)局域網(wǎng)所以無(wú)法連接液样。
解決方案是在 broker.conf
配置文件中增加 brokerIP1=宿主機(jī)IP
即可
POM
主要增加了 org.springframework.cloud:spring-cloud-starter-stream-rocketmq
依賴
<?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>
<parent>
<groupId>com.funtl</groupId>
<artifactId>hello-spring-cloud-alibaba-dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../hello-spring-cloud-alibaba-dependencies/pom.xml</relativePath>
</parent>
<artifactId>hello-spring-cloud-alibaba-rocketmq-provider</artifactId>
<packaging>jar</packaging>
<name>hello-spring-cloud-alibaba-rocketmq-provider</name>
<url>http://www.funtl.com</url>
<inceptionYear>2018-Now</inceptionYear>
<dependencies>
<!-- Spring Boot Begin -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Spring Boot End -->
<!-- Spring Cloud Begin -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
</dependency>
<!-- Spring Cloud End -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.funtl.hello.spring.cloud.alibaba.rocketmq.provider.RocketMQProviderApplication</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
消息生產(chǎn)者服務(wù)
package com.funtl.hello.spring.cloud.alibaba.rocketmq.provider.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
@Service
public class ProviderService {
@Autowired
private MessageChannel output;
public void send(String message) {
output.send(MessageBuilder.withPayload(message).build());
}
}
Application
配置 Output(Source.class
) 的 Binding 信息并配合 @EnableBinding
注解使其生效
package com.funtl.hello.spring.cloud.alibaba.rocketmq.provider;
import com.funtl.hello.spring.cloud.alibaba.rocketmq.provider.service.ProviderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
@SpringBootApplication
@EnableBinding({Source.class})
public class RocketMQProviderApplication implements CommandLineRunner {
@Autowired
private ProviderService providerService;
public static void main(String[] args) {
SpringApplication.run(RocketMQProviderApplication.class, args);
}
/**
* 實(shí)現(xiàn)了 CommandLineRunner 接口,只是為了 Spring Boot 啟動(dòng)時(shí)執(zhí)行任務(wù)巧还,不必特別在意
* @param args
* @throws Exception
*/
@Override
public void run(String... args) throws Exception {
providerService.send("Hello RocketMQ");
}
}
application.yml
spring:
application:
name: rocketmq-provider
cloud:
stream:
rocketmq:
binder:
# RocketMQ 服務(wù)器地址
namesrv-addr: 192.168.10.149:9876
bindings:
# 這里是個(gè) Map 類(lèi)型參數(shù)鞭莽,{} 為 YAML 中 Map 的行內(nèi)寫(xiě)法
output: {destination: test-topic, content-type: application/json}
server:
port: 9093
management:
endpoints:
web:
exposure:
include: '*'
運(yùn)行成功后即可在 RocketMQ 控制臺(tái)的 消息
列表中選擇 test-topic
主題即可看到發(fā)送的消息