Please check gitee for the following related project configuration https://gitee.com/xwb1056481167/spring-cloud
What is SpringCloudStream
The official website defines Spring cloud Stream as a framework for building message-driven microservices. The application interacts with the binder object in Spring Cloud Stream through inputs and outputs. Through our configuration, we bind (bind) and the binder object of Spring Cloud Stream is responsible for interacting with the message middleware. Therefore, we only need to figure out how to interact with Spring CloudStream to conveniently use the message-driven approach.
Why introduce
By using Spring Integration to connect the message broker middleware to achieve message-driven event-driven, Spring Cloud Stream provides personalized automated configuration implementations for some vendors’ message middleware products, applying the three types of publish-subscribe, consumer group, and partition. Core concepts. Only support RabbitMQ, Kafka Chinese help manual
https://m.wang1314.com/doc/webapp/topic/20971999.html
springCloudStream standard process
Component |
Description |
---|---|
Middleware |
Middleware, currently only supports RabbitMQ, Kafka |
Binder |
Binder is applied to the encapsulation between message middleware. At present, the Binder of Kafka and RabbitMQ is implemented. Through Binder, the middleware can be easily linked, and the message type can be dynamically changed (corresponding to the topic of Kafka and the exchange of RabbitMQ). These are all Can be achieved through configuration files |
@Input |
Annotation indicates an input channel, and messages received through this input channel enter the application |
@Output |
Represents the annotation output channel through which the published message will leave the application |
@StreamListener |
The listening queue is used for the message reception of the consumer's queue |
@EnableBinding |
Refers to the channel channel and exchange are bound together |
Integration of consumers and providers
Message provider cloud-stream-rabbitmq-provider8801
1 、 pom.xml
<!-- stream rabbitmq -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
<!-- 添加rabbitmq的支持 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
2. The core configuration of yml
spring:
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 #设置要绑定的额消息服务的具体设置
3. The main startup class
@SpringBootApplication
@EnableDiscoveryClient
public class StreamMQMain8801 {
public static void main(String[] args) {
SpringApplication.run(StreamMQMain8801.class,args);
}
}
4. Core configuration sender
// 1、接口
public interface IMessageProvider {
public String send();
}
//2、接口实现类
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;
import org.xwb.springcloud.service.IMessageProvider;
import javax.annotation.Resource;
import java.util.UUID;
/**
* 定义消息的推送管道
* 里面注入的内容都是message的,谨记不是注入dao、或其他什么,
*/
@EnableBinding(Source.class)
public class IMessageProviderImpl implements IMessageProvider {
@Resource
private MessageChannel output;
@Override
public String send() {
String serial = UUID.randomUUID().toString();
output.send(MessageBuilder.withPayload(serial).build());
System.out.println("****************serial:"+serial);
return serial;
}
}
//3、controller发送
@RestController
public class SendMessageController {
@Resource
private IMessageProvider messageProvider;
@GetMapping("/sendMessage")
public String sendMessage() {
return messageProvider.send();
}
}
Note: @EnableBinding and MessageChannel are introduced in the jar package, both of which depend on cloud.stream.*
Message consumers 8802, 8803
The configuration of 8002 and 8003 are the same, only the port number is different, here it means that the configuration of 8002.8003 is the same as the
new module cloud-stream-rabbitmq-consumer8802
1 、 pom.xml
<!-- stream rabbitmq -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
<!-- 添加rabbitmq的支持 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
2 、 l 配置
spring:
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 #设置要绑定的额消息服务的具体设置
Note: bindings.input. Here, the consumer needs to get the message from the channel and input it into the sink to read it.
3. The main startup class
@SpringBootApplication
@EnableDiscoveryClient
public class StreamMQMain8802 {
public static void main(String[] args) {
SpringApplication.run(StreamMQMain8802.class, args);
}
}
4. Message receiving and consumption
@Component
@EnableBinding(Sink.class)
public class ReceiveMessageListenerController {
@Value("\${server.port}")
private String serverPort;
@StreamListener(Sink.INPUT)
public void receiveMessage(@Payload String in, @Header(AmqpHeaders.CONSUMER_QUEUE) String queue) {
System.out.println("消费者"+serverPort+"收到的消息为-->:"+in + " received from queue " + queue);
}
}
Note: @EnableBinding and MessageChannel are introduced in jar packages, which are dependencies of cloud.stream.*.
Create the 8003 project in accordance with 8002.
test
Start 7001, 8801 producers, 8002, 8003 consumers, enter the get request in the address bar to send a message
http://localhost:8801/sendMessage
The peak change of rabbitmq
8802 and 8803 received message results
Group consumption and persistence
Question: The messages sent by 8801 will be consumed by 8802 and 8803. How to solve the problem.
Principle: When the microservice applications are placed in the same group, it can be guaranteed that the message will only be consumed by one of the applications once, and
different groups can be sub-Orpheid. , The same group will have a competitive relationship, and only one of them can consume.
Grouping
1. So the solution is to put them in the same group
spring:
application:
name: cloud-stream-customer #服务名
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 #设置要绑定的额消息服务的具体设置
group: consumerA
Join the same group: group: consumerA can avoid repeated consumption
Endurance
If one of 8802 and 8803 is configured with grouping, and the other is cancelled, the consumer configured with grouping will automatically consume the message sent by the 8801 sender after the consumer restarts. Make the message persistent.
Proof: The group must be configured