1 Overview
What is it?
Spring Cloud Stream is a framework for building message microservices. It can shield the differences in the underlying message middleware and reduce the cost of version switching. The unified messaging programming model currently only supports RabbitMQ and Kafka.
Design ideas
The design idea of standard MQ.
-
Producers/consumers rely on message media to transfer information content, Message
-
The message must go through a specific channel, MessageChannel
-
How are the messages in the message channel consumed, and who is responsible for receiving and sending them? The sub-interface SubscribableChannel of the message channel MessageChannel is responsible for sending and processing, and it can be consumed after being subscribed by the message handler MessageHandler.
Design Ideas of Spring Cloud Stream
inputs correspond to consumers, outputs correspond to producers
The message communication method in Stream follows the publish-subscribe model, and broadcasts with Topic topics (in RabbitMQ it is Exchange, in Kafka it is Topic)
work process
-
Binder: binder, it is very convenient to connect middleware, shielding differences
-
Channel: Channel is an abstraction of Queue. In the message communication system, it is the medium for storage and forwarding. The queue is configured through Channel
-
Source and Sink: The simple understanding is that the reference is Spring Cloud Stream itself. Publishing messages from Stream is the output (Source), and receiving messages is the input (Sink).
Coding API and common annotations
2.HelloWord
First create a springboot project.
Introduce dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
Configure rabbitmq:
spring.rabbitmq.host=rabbitmq地址
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.port=5672
Create RabbitMQ
a class for receiving messages from:
@EnableBinding(Sink.class)
public class MyReceiver {
public static final Logger logger = LoggerFactory.getLogger(MyReceiver.class);
@StreamListener(Sink.INPUT)
public void reveicer(Object payload){
logger.info("Receiver:"+payload);
}
}
At this time, you can see from the log that rabbitmq
the connection has been established
when starting the project. At this time, you can see on the rabbitmq
management side that a pointed 36.148.83.121
connection has been established .
And you can see a named input.anonymous.cXRH-vL2T5eQJoTUtHi5tQ
queue in the queue list .
Next, enter input.anonymous.cXRH-vL2T5eQJoTUtHi5tQ
the queue management page, through the Publish Message
function to send a message to the queue.
At this time, you can see the message just sent in the console.
3. Custom message channel
First create an Mychannel
interface named :
public interface MyChannel {
String INPUT = "pikachues-input";
String output = "pikachues-output";
@Output(output)
MessageChannel output();
@Input(INPUT)
SubscribableChannel input();
}
Note:
1. The names of the two message channels are different, otherwise there will be problems.
2. Starting from the F version, the channel name is used as the instance command by default, so the channel name cannot be the same here (the earlier version can be the same). In this case, in order to send and receive messages normally, we need to do some additional configuration in application.properties
Now do the following configuration in application.peoperties:
# 发送接收通道名称不同,但是主题(广播站名称)名称必须相同
spring.cloud.stream.bindings.pikachues-input.destination=pikachues-topic
spring.cloud.stream.bindings.pikachues-output.destination=pikachues-topic
Receipt of custom messages:
@EnableBinding(MyChannel.class)
public class MyReceiver2 {
public final static Logger logger = LoggerFactory.getLogger(MyReceiver2.class);
@StreamListener(MyChannel.INPUT)
public void receiver(Object playload){
logger.info("receiver2"+playload);
}
}
Custom message sending:
@RestController
public class SendMessageController {
@Autowired
MyChannel myChannel;
@GetMapping("/hello")
public void hello(){
myChannel.output().send(MessageBuilder.withPayload("hello springcloud stream").build());
}
}
Restart the project and call the calling interface /hello
, and you can see SendMessageController
the message being sent in the console .
4. Consumption grouping
By default, if the consumer is a cluster, Sring Cloud Stream will assign each consumer an independent anonymous consumer group. At this time, after the message is sent, every application of the same topic will consume, which causes Repeat consumption. Therefore, it is best to specify a consumption group for each consumer to prevent repeated consumption.
Consumption grouping only needs to do the following configuration in the configuration file:
spring.cloud.stream.bindings.pikachues-input.group=g1
pikachues-input
Is the consumer channel name. There is a competitive relationship between different consumers in the same group, and only one will be consumed
5. Consumption partition
After introducing the consumer group, we can ensure that each message is only consumed by one instance in the group in the consumer cluster, but we don't know which consumer instance is consumed. At this time, the message partition can help us solve the problem.
The consumption partition needs to be configured separately on the message provider and message consumer.
The consumer configuration is as follows:
# 开启消费者分区功能
spring.cloud.stream.bindings.pikachues-input.consumer.partitioned= true
# 当前消费者的总实例个数
spring.cloud.stream.instance-count=2
# 当前实例的索引号,从0开始,
spring.cloud.stream.instance-index=0
Message provider configuration:
# 指定了分区键的表达式规则,例如当表达式的值为1, 那么在订阅者的instance-index中为1的接收方, 将会执行该消息.
spring.cloud.stream.bindings.pikachues-output.producer.partition-key-expression=0
# 指定消息分区的数量
spring.cloud.stream.bindings.pikachues-output.producer.partition-count= 2