[spring cloud learning note 8] use and precautions of spring cloud stream

Keywords: Spring RabbitMQ JSON Programming

Use of spring cloud stream

1, Introduction to SpringCloud Stream

In the actual development, there are various kinds of message processing middleware (MQ), but if you learn all MQ, the learning cost is too high, and the emergence of spring cloud stream can ignore the difference of message middleware used at the bottom, reduce the switching cost, and unify the programming model of message.

Official note

Spring Cloud Stream is a framework for building highly scalable event-driven microservices connected with shared messaging systems.

The framework provides a flexible programming model built on already established and familiar Spring idioms and best practices, including support for persistent pub/sub semantics, consumer groups, and stateful partitions.

Spring Cloud Stream is a framework for building highly scalable event driven microservices connected to shared messaging systems.

The framework provides a flexible programming model based on established and familiar Spring idioms and best practices, including support for persistent publish / sub semantics, consumer groups, and stateful partitioning.

1.Stream usage

Interaction mode:

  • The application interacts with the binder object in Spring Cloud Stream through inputs or outputs.
  • After the binding is configured, the Spring Cloud Stream's binder object interacts with the message middleware.

Therefore, we only need to interact with Spring Cloud Stream, and then this middleware will help us transform and interact.
Using Spring Integration to connect the message broker middleware to achieve message event driven.

Currently, only RabbitMQ and Kafka are supported

Spring Cloud Stream guide in Chinese

2, About Binder

Binder, as the middle layer, realizes the isolation between application and message middleware details (corresponding to the exchange of rabbitMQ and the Topic of kafka)

Input in binder corresponds to message consumer

Output in binder corresponds to message producer

3, Stream common comments

@Input

Annotation identifies the input channel through which information received enters the application

@Output

Annotation identifies the output channel through which published messages leave the application

@StreamListener

Listening queue, used for receiving queue messages of consumers

@EnableBinding

Channel and exchange are bound together

4, Stream operation

1. Build message producers

1. Building sub modules

2. Modify pom file

Added spring cloud starter stream rabbit

<dependencies>
    <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-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
    </dependency>
    <!--Basic configuration-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

3. Preparation of yml documents

server:
  port: 8801

spring:
  application:
    name: cloud-stream-provider
  cloud:
    stream:
      binders: # Configure the service information of rabbitmq to be bound here;
        defaultRabbit: # Represents the name of the definition used for binding integration
          type: rabbit # Message component type
          environment: # Setting up the relevant environment configuration of rabbitmq
            spring:
              rabbitmq:
                host: 192.168.1.50
                port: 5672
                username: guest
                password: guest
      bindings: # Integration of services
        output: # This name is the name of a channel
          destination: studyExchange # Represents the Exchange name definition to use
          content-type: application/json # Set the message type. This time, it is json, and the text is "text/plain"
          binder: defaultRabbit # Set the specific settings of the message service to be bound

eureka:
  client: # Configuration of Eureka registration by client
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    lease-renewal-interval-in-seconds: 2 # Set heartbeat interval (default is 30 seconds)
    lease-expiration-duration-in-seconds: 5 # If the interval of 5 seconds is exceeded now (the default is 90 seconds)
    instance-id: send-8801.com  # Show host name in message list
    prefer-ip-address: true     # Access path changed to IP address

binder: defaultRabbit reports red here, but does not affect the operation

4. Main method of compilation

@SpringBootApplication
public class StreamProviderMain8801 {
    public static void main(String[] args){
        SpringApplication.run(StreamProviderMain8801.class,args);      
        
    }
}

5. Write service

public interface IMessageService {
    public String send();
}
@EnableBinding(Source.class)//Define push pipeline for messages
@Slf4j
public class MessageServiceImpl implements IMessageService {

    @Resource
    private MessageChannel output;

    @Override
    public String send() {
        String serial = UUID.randomUUID().toString();
        output.send(MessageBuilder.withPayload(serial).build());
        log.info("*********serial:" + serial);
        return null;
    }
}

6. Write controller

@RestController
public class MessageController {

    @Resource
    private IMessageService messageService;

    @GetMapping("/sendmsg")
    public String send() {
        return messageService.send();
    }
}

2. Build message consumers

1. Building sub modules

2. Modify pom

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <!--Basic configuration-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

3. Write yml

Two consumers are opened here. Only the name and port number of eureka on the face need to be changed

server:
  port: 8802

spring:
  application:
    name: cloud-stream-consumer
  cloud:
    stream:
      binders: # Configure the service information of rabbitmq to be bound here;
        defaultRabbit: # Represents the name of the definition used for binding integration
          type: rabbit # Message component type
          environment: # Setting up the relevant environment configuration of rabbitmq
            spring:
              rabbitmq:
                host: 192.168.1.50
                port: 5672
                username: guest
                password: guest
      bindings: # Integration of services
        input: # This name is the name of a channel
          destination: studyExchange # Represents the Exchange name definition to use
          content-type: application/json # Set the message type. This time it is the object json. If it is text, set "text/plain"
          binder: defaultRabbit # Set the specific settings of the message service to be bound



eureka:
  client: # Configuration of Eureka registration by client
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    lease-renewal-interval-in-seconds: 2 # Set heartbeat interval (default is 30 seconds)
    lease-expiration-duration-in-seconds: 5 # If the interval of 5 seconds is exceeded now (the default is 90 seconds)
    instance-id: receive-8802.com  # Show host name in message list
    prefer-ip-address: true     # Access path changed to IP address

Note that consumers use input

  bindings: # Integration of services
    input: # This name is the name of a channel
      destination: studyExchange # Represents the Exchange name definition to use
      content-type: application/json # Set the message type. This time it is the object json. If it is text, set "text/plain"
      binder: defaultRabbit # Set the specific settings of the message service to be bound

4. Main method of compilation

@SpringBootApplication
public class StreamConsumerMain8802 {
    public static void main(String[] args){
        SpringApplication.run(StreamConsumerMain8802.class,args);      
        
    }
}

5. Create message add component Controller

@EnableBinding(Sink.class)
public class ReciveMessageController {

    @Value("${server.port}")
    private String serverPort;

    @StreamListener(Sink.INPUT)
    //import org.springframework.messaging.Message;
    public void recive(Message<String> message) {
        System.out.println("consumer"+serverPort+"\t Information received:"+message.getPayload());
    }
}

5, Stream message grouping

1. Repeated consumption

After the above operations are completed, it is found that if a message is sent, both sides will receive it, that is, a message will be consumed by two consumers at the same time

In actual projects, if the nature of consumption is the same, we should not consume both, but compete for one consumption

At this time, messages need to be grouped. The same group competes for messages and different groups receive them

2. Message persistence

If a server is not grouped, if the server is shut down, the last message will not be received;

If the packet is used and the service is restarted, it can receive the last message. This is message persistence

3. Enable grouping mode

Overwrite yml file

bindings: # Integration of services
  input: # This name is the name of a channel
    destination: studyExchange # Represents the Exchange name definition to use
    content-type: application/json # Set the message type. This time it is the object json. If it is text, set "text/plain"
    binder: defaultRabbit # Set the specific settings of the message service to be bound
    group: GroupA

When on, polling mode is on by default

6, Summary

1. Learning summary

Spring Cloud Stream uses binder interaction, which can ignore the layer message middleware, and then help us transform and interact.

Currently, only RabbitMQ and Kafka are supported

2. Precautions

When configuring the yml configuration, the binder: defaultRabbit reports red here, but does not affect the operation

Posted by Ziq on Fri, 26 Jun 2020 22:24:45 -0700