SpringCloud微服务之消息驱动-stream的使用
SpringCloud微服务之消息驱动-stream的使用)
前言
springcloud技术栈:
一、简介
Spring Cloud Stream是一个用于构建消息驱动的微服务应用程序的框架。Spring Cloud Stream构建在Spring Boot之上,以创建独立的生产级Spring应用程序,并使用Spring Integration提供与消息代理的连接。它提供了来自多个供应商的中间件的个性化配置,引入了持久发布-订阅语义、消费者组和分区的概念。用Spring Cloud Stream的说法,这些被称为绑定器实现。开箱即用,Spring Cloud Stream为Apache Kafka和RabbitMQ提供了绑定器实现。我使用的是RabbitMQ。
二、服务端
1.pom
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2.yml
server:
port: 8801
spring:
application:
name: cloud-stream-provider
cloud:
stream:
binders: # 在此处配置要绑定的rabbitmq的服务信息;
defaultRabbit: # 表示定义的名称,用于于binding整合
type: rabbit # 消息组件类型
environment: # 设置rabbitmq的相关的环境配置
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
bindings: # 服务的整合处理
output: # 这个名字是一个通道的名称
destination: studyExchange # 表示要使用的Exchange名称定义
content-type: application/json # 设置消息类型,本次为json,文本则设置“text/plain”
binder: defaultRabbit # 设置要绑定的消息服务的具体设置
eureka:
client: # 客户端进行Eureka注册的配置
service-url:
defaultZone: http://localhost:7001/eureka
instance:
lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
instance-id: receive-8801.com # 在信息列表时显示主机名称
prefer-ip-address: true # 访问的路径变为IP地址
3.启动类
@SpringBootApplication
public class StreamProvider8801Main {
public static void main(String[] args) {
SpringApplication.run(StreamProvider8801Main.class, args);
}
}
4.业务类
service:
public interface IMsgProviderService {
String send();
}
Impl:
@EnableBinding(Source.class)
public class MsgProviderImpl implements IMsgProviderService {
/**
* 消息发送管道/信道
*/
@Resource
private MessageChannel output;
@Override
public String send() {
String serial = UUID.randomUUID().toString();
Message<String> stringMessage = MessageBuilder.withPayload(serial).build();
output.send(stringMessage);
System.out.println("*****serial: " + serial);
return serial;
}
}
5.controller
@RestController
public class providerController {
@Resource
private IMsgProviderService messageProviderService;
@GetMapping(value = "/sendMessage")
public String sendMessage() {
return messageProviderService.send();
}
}
二、消费端
1.pom
<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.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2.yml
消费端bindings下的是input配置,服务端是ouput输出。
server:
port: 8802
spring:
application:
name: cloud-stream-consumer
cloud:
stream:
binders: # 在此处配置要绑定的rabbitmq的服务信息;
defaultRabbit: # 表示定义的名称,用于于binding整合
type: rabbit # 消息组件类型
environment: # 设置rabbitmq的相关的环境配置
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
bindings: # 服务的整合处理
input: # 这个名字是一个通道的名称
destination: studyExchange # 表示要使用的Exchange名称定义
content-type: application/json # 设置消息类型,本次为json,文本则设置“text/plain”
binder: defaultRabbit # 设置要绑定的消息服务的具体设置
eureka:
client: # 客户端进行Eureka注册的配置
service-url:
defaultZone: http://localhost:7001/eureka
instance:
lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
instance-id: receive-8802.com # 在信息列表时显示主机名称
prefer-ip-address: true # 访问的路径变为IP地址
3.启动类
@SpringBootApplication
public class StreamConsumer8802Main {
public static void main(String[] args) {
SpringApplication.run(StreamConsumer8802Main.class, args);
}
}
4.controller
@EnableBinding(Sink.class),服务端是Source.class。
@Component
@EnableBinding(Sink.class)
public class consumer8802Controller {
@Value("${server.port}")
private String serverPort;
@StreamListener(Sink.INPUT)
public void input(Message<String> message) {
System.out.println("port:" + serverPort + "\t接受:" + message.getPayload());
}
}
三、测试
启动,服务端发送消息,可以看到消费端成功消费消息,即配置成功。
四、重复消费和持久化
复制多个消费端模块,在启动会发现消息会被多个消费端重复消费。
只需要再客户端yml配置group参数即可:客户端配置同一个消费组名字,他们之间变成了竞争关系,就可以解决重复消费问题。
bindings: # 服务的整合处理
input: # 这个名字是一个通道的名称
destination: studyExchange # 表示要使用的Exchange名称定义
content-type: application/json # 设置消息类型,本次为json,文本则设置“text/plain”
binder: defaultRabbit # 设置要绑定的消息服务的具体设置
group: GropuA