Spring Cloud Stream easy to use

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.
Insert picture description here

  • 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

Insert picture description here
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

Insert picture description here

  • 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

Insert picture description here

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 RabbitMQa 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 rabbitmqthe connection has been established
Insert picture description here
when starting the project. At this time, you can see on the rabbitmqmanagement side that a pointed 36.148.83.121connection has been established .
Insert picture description here
And you can see a named input.anonymous.cXRH-vL2T5eQJoTUtHi5tQqueue in the queue list .
Insert picture description here
Next, enter input.anonymous.cXRH-vL2T5eQJoTUtHi5tQthe queue management page, through the Publish Messagefunction to send a message to the queue.
Insert picture description here
At this time, you can see the message just sent in the console.
Insert picture description here

3. Custom message channel

First create an Mychannelinterface 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 SendMessageControllerthe message being sent in the console .
Insert picture description here

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-inputIs 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

Guess you like

Origin blog.csdn.net/qq_41262903/article/details/106225752