A detailed explanation of the source code analysis and actual combat of RocketMQ-Spring

Abstract: This article mainly introduces the operation process of Spring Boot project using rocketmq-spring SDK to realize message sending and receiving. At the same time, the author will interpret the design logic of SDK from the perspective of developers.

This article is shared from the Huawei Cloud Community " RocketMQ-Spring: Combat and source code analysis in one go ", author: Brother Yongjava practical sharing.

RocketMQ is a well-known message queue. The open source project rocketmq-spring can help developers quickly integrate RocketMQ in Spring Boot projects.

This article will introduce the operation process of the Spring Boot project using the rocketmq-spring SDK to realize message sending and receiving . At the same time, the author will interpret the design logic of the SDK from the perspective of developers .  

1 SDK Introduction

Project address: https://github.com/apache/rocketmq-spring

The essence of rocketmq-spring is a Spring Boot starter  .

Spring Boot is based on the concept of " convention over configuration " (Convention over configuration) to quickly develop, test, run and deploy Spring applications, and can be easily combined with various starters (such as spring-boot-web-starter) , allowing the application to run directly from the command line without deploying it in a separate container.

The starter constructed by Spring Boot starter is very convenient to use. Developers only need to introduce the dependency definition of the starter in pom.xml, and write the agreed configuration in the configuration file . 

Let's look at the configuration of rocketmq-spring-boot-starter:

1. Introduce dependencies

<dependency>
 <groupId>org.apache.rocketmq</groupId>
 <artifactId>rocketmq-spring-boot-starter</artifactId>
 <version>2.2.3</version>
</dependency>

2. Agreed configuration

Next, we explain the operation process of message sending and receiving in detail in the order of producers and consumers respectively.

Second producer

First, after we add dependencies, we proceed with the following three steps:

1. The configuration file is configured as follows

rocketmq:
  name-server: 127.0.0.1:9876
  producer:
      group: platform-sms-server-group
    # access-key: myaccesskey
    # secret-key: mysecretkey
  topic: sms-common-topic

The producer configuration is very simple, mainly configuring the name service address and producer group .

2. Inject RcoketMQTemplate into the class that needs to send messages 

@Autowired
private RocketMQTemplate rocketMQTemplate;
@Value("${rocketmq.topic}")
private String smsTopic;

3. To send a message, the message body can be a custom object or a Message object

The rocketMQTemplate class contains several methods for sending messages:

  1. Synchronous send syncSend
  2. Asynchronous sending asyncSend
  3. Send in order syncSendOrderly
  4. oneway send sendOneWay

The code below shows how to send messages synchronously.

String destination = StringUtils.isBlank(tags) ? topic : topic + ":" + tags;
SendResult sendResult =
 rocketMQTemplate.syncSend(
            destination, 
 MessageBuilder.withPayload(messageContent).
 setHeader(MessageConst.PROPERTY_KEYS, uniqueId).
 build()
 );
if (sendResult != null) {
 if (sendResult.getSendStatus() == SendStatus.SEND_OK) {
 // send message success ,do something 
 }
}

The first parameter of the syncSend method is the target to send, the format is: topic + ":" + tags  ,

The second parameter is: the message object of the spring-message specification , and MessageBuilder is a tool class, and the method chain call creates the message object.

Three consumers

1. The configuration file is configured as follows

rocketmq:
  name-server: 127.0.0.1:9876
  consumer1:
    group: platform-sms-worker-common-group
    topic: sms-common-topic

2. Implement the message listener

@Component
@RocketMQMessageListener(
 consumerGroup = "${rocketmq.consumer1.group}", //消费组
    topic = "${rocketmq.consumer1.topic}" //主题
)
public class SmsMessageCommonConsumer implements RocketMQListener<String> {
 public void onMessage(String message) {
 System.out.println("普通短信:" + message);
 }
}

The consumer implementation class can also implement RocketMQListener<MessageExt>, and obtain more detailed message data through the RocketMQ native message object MessageExt in the onMessage method .     

public void onMessage(MessageExt message) {
 try {
        String body = new String(message.getBody(), "UTF-8");
        logger.info("普通短信:" + message);
 } catch (Exception e) {
 logger.error("common onMessage error:", e);
 }
}

Four source code overview

In the latest source code, we can see that the source code contains four modules:

1、rocketmq-spring-boot-parent

This module is the parent module, which defines all dependent jar packages of the project.

2、rocketmq-spring-boot

The core module implements the core logic of the starter.

3、rocketmq-spring-boot-starter

SDK module, simple package, external project reference.

4、rocketmq-spring-boot-samples

Sample code module. This module is very important. When users use the SDK, they can refer to the examples for rapid development.

Five starter implementations

We focus on analyzing the core source code of the rocketmq-spring-boot module:

The spring-boot-starter implementation needs to contain the following three parts:

1. Define Spring's own dependency packages and RocketMQ 's dependency packages ;   

2. Define the spring.factories file 

After creating the META-INF directory under the resources package, create a new spring.factories file and define the autoloading class in the file . The file content is:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration

Spring boot will automatically initialize the related Bean, Component or Service according to the automatic configuration class configured in the file.

3. Realize automatic loading class

In the specific implementation of the RocketMQAutoConfiguration class, we focus on analyzing how the producer and the consumer are started separately.

▍Producer sending template class: RocketMQTemplate

The RocketMQAutoConfiguration class defines two default beans:

First, the configuration values ​​in the configuration file in the SpringBoot project will be bound to the RocketMQProperties object according to the attribute conditions, and then use the native API of RocketMQ to create the producer bean and pull the consumer bean respectively, and set the two beans into the RocketMQTemplate object respectively.

Two important points need to be emphasized:

  • When sending a message, encapsulate the message object under the spring-message specification into a RocketMQ message object
  • By default, the consumer litePullConsumer is pulled. Pull consumers are generally used in large data batch processing scenarios.

The RocketMQTemplate class encapsulates the receive method of pulling consumers for the convenience of developers.

▍Custom consumer class

The following figure is an example of concurrent consumers:

So how does rocketmq-spring automatically start consumers?

The spring container first registers the post-processor of the message listener , and then calls the registerContainer method of the ListenerContainerConfiguration class.

Comparing the examples of concurrent consumers, we can see that: DefaultRocketMQListenerContainer encapsulates the consumption logic of DefaultMQPushConsumer.

Encapsulate the logic of consuming messages , and at the same time meet the RocketMQListener generalization interface to support different parameters , such as String, MessageExt, and custom objects.  

First, after the DefaultRocketMQListenerContainer is initialized, get the parameter type of the onMessage method.

Then when the consumer calls consumeMessage to process the message, it encapsulates a handleMessage method, converts the native RocketMQ message object MessageExt into the parameter object defined by the onMessage method, and then calls the onMessage method of rocketMQListener.

The code marked in red on the right side of the figure above is the essence of the method:

rocketMQListener.onMessage(doConvertMessage(messageExt));

Six to the end

The open source project rocketmq-spring has a lot to learn, and we can advance step by step from the following four levels:

1. Learn how to use  : refer to the sample code of the rocketmq-spring-boot-samples module, learn how to send and receive messages, and quickly code;

2. Module design : the module hierarchy of the learning project (parent module, SDK module, core implementation module, sample code module);

3. Starter design idea  : define automatic configuration file spring.factories, design configuration attribute classes, realize elegant encapsulation on the basis of RocketMQ client, deeply understand RocketMQ source code, etc.;

4. Inference : When we understand the source code of rocketmq-spring, we can try to imitate the project and write a simple spring boot starter.

 

Click to follow and learn about Huawei Cloud's fresh technologies for the first time~

{{o.name}}
{{m.name}}

Guess you like

Origin my.oschina.net/u/4526289/blog/8687741