Spring Cloud Alibaba technology stack

Posted by jaygattis on Mon, 29 Nov 2021 06:29:06 +0100

Spring Cloud Alibaba Dubbo

1, Project introduction

Dubbo Spring Cloud is developed based on Dubbo Spring Boot 2.7.1 and Spring Cloud 2.x. whether the developer is a Dubbo user or a Spring Cloud user, it can be easily controlled and the application can be migrated upward at a cost close to "zero". Dubbo Spring Cloud is committed to simplifying Cloud Native development costs, improving R & D efficiency and application performance.

The first Preview Release of Dubbo Spring Cloud was released together with Spring Cloud Alibaba 0.2.2.RELEASE and 0.9.0.RELEASE, corresponding to Spring Cloud Finchley and Greenwich respectively (hereinafter referred to as "F" version and "G" version respectively)

2, Function completion

Since Dubbo Spring Cloud is built on the native Spring Cloud, its service governance capability can be considered as Spring Cloud Plus, which not only completely covers the native features of Spring Cloud, but also provides a more stable and mature implementation. The feature comparison is shown in the following table:

3, Construction of framework

We will build the project framework as shown in the figure

3.1 build spring cloud Dubbo examples

Spring cloud Dubbo exmaps is a parent project used to version control and remove public dependencies for child projects.

3.1.1 create project

Create a module using IDEA:

Select Maven:

Click Next to proceed to the Next step:

Parent: you must select the spring cloud Alibaba examples we created earlier.
Name: the name of the spring cloud Dubbo examples project
Click Finish to finish creating the project.

So far, the spring cloud Dubbo examples project has been created.

3.1.2 add dependency

Open pom.xml of the project and add the following:

<dependencies>
	<dependency>
		<groupId>com.alibaba.cloud</groupId>
		<artifactId>spring-cloud-starter-dubbo</artifactId>
	</dependency>
	<dependency>
		<groupId>com.alibaba.cloud</groupId>
		<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
	</dependency>
</dependencies>

3.1.3 modify the packaging method of the project

<packaging>pom</packaging>

3.1.4 the complete pom.xml file is as follows

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<parent>
		<artifactId>spring-cloud-alibaba-examples</artifactId>
		<groupId>com.bjsxt</groupId>
		<version>1.0</version>
	</parent>
	<modelVersion>4.0.0</modelVersion>
	<packaging>pom</packaging>
	<artifactId>spring-cloud-dubbo-examples</artifactId>
	<dependencies>
		<dependency>
			<groupId>com.alibaba.cloud</groupId>
			<artifactId>spring-cloud-starter-dubbo</artifactId>
		</dependency>
		<dependency>
			<groupId>com.alibaba.cloud</groupId>
			<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
		</dependency>
	</dependencies>
</project>

3.2 build Dubbo API

The Dubbo API will store interfaces for publishing services.

3.2.1 creating Dubbo API project

Create a sub module using IDEA.

Select Maven project:

Click Next to proceed to the Next step:

Parent: select spring cloud Dubbo examples
Name: Dubbo API
Click Finish to finish creating the project:

3.2.2 the complete pom.xml file is as follows

The pom.xml file of Dubbo API is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<parent>
		<artifactId>spring-cloud-dubbo-examples</artifactId>
		<groupId>com.bjsxt</groupId>
		<version>1.0</version>
	</parent>
	<modelVersion>4.0.0</modelVersion>
	<artifactId>dubbo-api</artifactId>
</project>

3.3 build Dubbo provider

3.3.1 create Dubbo provider project

Build a Dubbo provider to be a service provider.
Create a module using IDEA:

Select Maven project:

Click Next to proceed to the Next step:

Parent: select spring cloud Alibaba examples
Name: dubbo-provider
Click Finish to finish creating the project.

3.3.2 modify Maven's packaging method

Maven project will be packaged in a jar by default by the class file in the target directory. This jar cannot be run directly. We need to modify its packaging method to spring boot packaging, so that the packaged project can be run directly.
Modify pom.xml and add the following content:

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>

In this way, the project will eventually be packaged into a jar that can be run directly through Java jar

3.3.3 complete pom.xml file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<parent>
		<artifactId>spring-cloud-dubbo-examples</artifactId>
		<groupId>com.bjsxt</groupId>
		<version>1.0</version>
	</parent>
	<modelVersion>4.0.0</modelVersion>
	<artifactId>dubbo-provider</artifactId>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

3.4 building Dubbo consumer

3.4.1 create Dubbo provider consumer project

Build a Dubbo provider to be a service provider.
Create a module using IDEA:


Select Maven project:

Click Next to proceed to the Next step:

Parent: select spring cloud Alibaba examples
Name: dubbo-consumer
Click Finish to finish creating the project.

3.4.2 modify Maven's packaging method

Maven project will be packaged in a jar by default by the class file in the target directory. This jar cannot be run directly. We need to modify its packaging method to spring boot packaging, so that the packaged project can be run directly.
Modify pom.xml and add the following content:

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>

In this way, the project will eventually be packaged into a jar that can be run directly through Java jar

3.4.3 the complete pom.xml file is as follows

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<parent>
		<artifactId>spring-cloud-dubbo-examples</artifactId>
		<groupId>com.bjsxt</groupId>
		<version>1.0</version>
	</parent>
	<modelVersion>4.0.0</modelVersion>
	<artifactId>dubbo-consumer</artifactId>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

3.4.4 complete project structure

4, Code perfection

4.1 improvement of Dubbo api code

4.1.1 define Dubbo service interface

Dubbo service interface is a remote communication contract between service provider and consumer, which is usually declared by ordinary Java interface.


The code is as follows:

public interface EchoService {
	String echo(String message);
}

4.1.2 project packaging

The Api project is mainly to publish the interfaces defined in rpc.
We can use Maven's normal packaging method to package the compiled class file into jar.

After successful packaging, the jar of the project is located at:

4.2 improvement of Dubbo provider code

4.2.1 add dependency

Add the following dependencies in the dependencies of pom.xml of Dubbo provider.

<dependencies>
	<dependency>
		<groupId>com.bjsxt</groupId>
		<artifactId>dubbo-api</artifactId>
		<version>1.0</version>
	</dependency>
</dependencies>

4.2.2 implement the interfaces defined in Dubbo API


The code is as follows:

@Service
public class EchoServiceImpl implements EchoService {

	@Override
	public String echo(String message) {
		return "[echo] Hello, " + message;
	}
}

4.2.3 add profile


The contents are as follows:

dubbo:
	scan:
		# dubbo service scan benchmark package
		base-packages: com.bjsxt.service.impl
	cloud:
		subscribed-services: dubbo-provider
	protocol:
		# dubbo protocol
		name: dubbo
		# dubbo protocol port (- 1 indicates auto increment port, starting from 20880)
		port: -1
	registry:
		# Mount to the Spring Cloud registry
		address: spring-cloud://localhost
spring:
	application:
		# Dubbo app name
		name: dubbo-provider
	main:
		# Spring Boot 2.1 needs to be set
		allow-bean-definition-overriding: true
	cloud:
		nacos:
			# Nacos service discovery and registration configuration
			discovery:
				server-addr: localhost:8848

4.2.4 startup


The code is as follows:

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

4.3 improvement of Dubbo consumer code

4.3.1 add dependency

Add the following dependencies in the dependencies of pom.xml of Dubbo consumer:

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<dependency>
		<groupId>com.bjsxt</groupId>
		<artifactId>dubbo-api</artifactId>
		<version>1.0</version>
	</dependency>
	<!-- Dubbo Spring Cloud Starter -->
	<dependency>
		<groupId>com.alibaba.cloud</groupId>
		<artifactId>spring-cloud-starter-dubbo</artifactId>
	</dependency>
	<dependency>
		<groupId>com.alibaba.cloud</groupId>
		<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
	</dependency>
</dependencies>

4.3.2 add profile


The contents are as follows:

dubbo:
	registry:
		# Mount to the Spring Cloud registry
		address: nacos://127.0.0.1:8848
	cloud:
		subscribed-services: dubbo-provider
server:
	port: 8080
spring:
	application:
	# Dubbo app name
	name: dubbo-consumer
	main:
		# Spring Boot 2.1 needs to be set
		allow-bean-definition-overriding: true
	cloud:
		nacos:
			# Nacos service discovery and registration configuration
			discovery:
				server-addr: 127.0.0.1:8848

4.3.3 startup


The code is as follows:

@EnableDiscoveryClient
@SpringBootApplication
@RestController
public class ConsumerServiceApplication {

	@Reference
	private EchoService echoService ;
	
	public static void main(String[] args) {
		SpringApplication.run(ConsumerServiceApplication.class,args) ;
	}
	
	@GetMapping("/rpc")
	public ResponseEntity<String> rpc(){
		return ResponseEntity.ok(String.format("Call result
	by%s",echoService.echo("info")));
	}
}

4.4 remote call test

  • Start the Nacos server
  • Start Dubbo provider
  • Start Dubbo consumer
    To view the Nacos console:
    http://localhost:8848/nacos/

    Browser access:

    The call has been successful;

5, Load balancing call test

5.1 start multiple service providers

Modify the code of the implementation class in the service provider:

Start multiple:



Use Clt+D again to copy one:

Start the 2:

Now, there are 3 sets running at the same time:

View Nacos:

5.2 call test using consumer load balancing

visit:
http://localhost:8080/rpc


Load balancing test succeeded.

Spring Cloud Alibaba RocketMQ

1, RocketMQ introduction


RocketMQ is an open source distributed messaging system. Based on highly available distributed cluster technology, RocketMQ provides low latency and highly reliable message publishing and subscription services. At the same time, it is widely used in many fields, including asynchronous communication decoupling, enterprise solutions, financial payment, telecommunications, e-commerce, express logistics, advertising marketing, social networking, instant messaging, mobile applications, mobile games, video, Internet of things, Internet of vehicles, etc.

It has the following characteristics:

  • It can ensure strict message order
  • Provide rich message pull mode
  • Efficient subscriber level scalability
  • Real time message subscription mechanism
  • 100 million message accumulation energy

2, RocketMQ basic usage

2.1 download RocketMQ

Open with browser:
http://rocketmq.apache.org/release_notes/release-notes-4.4.0/
The reason why we choose version 4.4.0 here is that our spring cloud alibaba version is 2.2.0.RELEASE, and the version of rocketMQ controlled in it is 4.4.0.

2.2 RocketMQ directory analysis

Copy the compressed package to the software directory and decompress it with the compression software.

Benchmark: contains some performance test scripts;
Bin: executable file directory;
Conf: configuration file directory;
Lib: third party dependence;
LICENSE: authorization information;
Note: version announcement;

2.3 configuring environment variables

Locate the dialog box for configuring environment variables:

Click new to create an environment variable:

  • Variable name: ROCKETMQ_HOME
  • Variable value: D:\devtools\rocketMQ\rocketmq-all-4.4.0-bin-release

2.4 startup of rocketmq

We go to ${rocketMQ}/bin and start and stop commands in this directory.

2.4.1 start NameServe


Note: do not close the pop-up black window.

2.4.2 starting Broker

./mqbroker.cmd -n localhost:9876

Of which:
-n localhost:9876 is to specify the address of the nameserver

2.5 stopping of rocketmq

Close the pop-up black box directly to stop the namesrv and broker of RocketMQ.

2.6 installation of rocketmq console

Rocketmq console can visualize MQ message sending!

2.6.1 download RocketMQ console

2.6.2 copy to the software directory

2.6.3 run the jar

java -jar rocketmq-console-ng-1.0.0.jar --rocketmq.config.namesrvAddr=127.0.0.1:9876


Of which:

After successful operation:
visit:
http://localhost:8080/#/

3, Introduction to Spring Cloud Stream

Spring Cloud Stream is a framework for building message based microservice applications. It creates a stand-alone spring application with production level based on SpringBoot, and uses Spring Integration to connect with Broker.
Spring Cloud Stream provides a unified abstraction of message oriented middleware configuration, and introduces the unified concepts of publish subscribe, consumer groups and partition. Spring Cloud Stream has two internal concepts: Binder and Binding:

  • Binder: a component integrated with external message middleware to create Binding. Each message middleware has its own binder implementation.

    For example:
    Kafka implements KafkaMessageChannelBinder, RabbitMQ implements RabbitMessageChannelBinder, and RocketMQMessageChannelBinder implements RocketMQ.

  • Binding: includes Input Binding and Output Binding.
    Binding provides a bridge between the message middleware and the Provider and Consumer provided by the application. It enables developers to only use the Provider or Consumer of the application to produce or consume data, and shields the contact between developers and the underlying message middleware.

4, Test framework construction

We will create a spring cloud bus rocketmq example project to test all its functions.

4.1 build spring cloud bus rocketmq example

Spring cloud bus rocketmq example will remove the common dependencies of sub modules.

4.1.1 create a Maven project using IDEA


Select Maven project:

Click Next and fill in the following contents:

Parent: we choose spring cloud Alibaba examples
Name: spring-cloud-bus-rocketmq-example
Other items remain unchanged.
Click Finish to complete the creation.

4.1.2 add dependency

Open the pom.xml file of the project, and we add the following content:

<dependencies>
	<dependency>
		<groupId>com.alibaba.cloud</groupId>
		<artifactId>spring-cloud-starter-bus-rocketmq</artifactId>
	</dependency>
	<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>
</dependencies>

4.1.3 complete pom.xml file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<parent>
		<artifactId>spring-cloud-alibaba-examples</artifactId>
		<groupId>com.bjsxt</groupId>
		<version>1.0</version>
	</parent>
	<modelVersion>4.0.0</modelVersion>
	<artifactId>spring-cloud-bus-rocketmq-example</artifactId>
	<packaging>pom</packaging>
	<modules>
		<module>rocketmq-produce-example</module>
	</modules>
	<dependencies>
		<dependency>
			<groupId>com.alibaba.cloud</groupId>
			<artifactId>spring-cloud-starter-bus-rocketmq</artifactId>
		</dependency>
		<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>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

4.2 build rocketmq produce example

produce represents the producer of the service and is used to send messages.

4.2.1 create a Maven project using IDEA


Select Maven:

Click Next to add the following:

Parent: spring-cloud-bus-rocketmq-example
Name: rocketmq-produce-example
Click Finish to finish creating the project

4.2.2 modify Maven's packaging method

We may need to publish this project using jar in the future. Here, we add the packaging plug-in of spring boot:

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>

4.2.3 the complete pom.xml file is as follows

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<parent>
		<artifactId>spring-cloud-bus-rocketmq-example</artifactId>
		<groupId>com.bjsxt</groupId>
		<version>1.0</version>
	</parent>
	<modelVersion>4.0.0</modelVersion>
	<artifactId>rocketmq-produce-example</artifactId>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

4.3 build rocketmq produce example

4.3.1 create a Maven item using IDEA


Select Maven:

Click Next to add the following:

Parent: spring-cloud-bus-rocketmq-example
Name: rocketmq-consumer-example
Click Finish to finish creating the project

4.3.2 modify Maven's packaging method

In order to package and publish as a jar in the future, we add a packaging plug-in:

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>

4.3.3 complete pom.xml file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<parent>
		<artifactId>spring-cloud-bus-rocketmq-example</artifactId>
		<groupId>com.bjsxt</groupId>
		<version>1.0</version>
	</parent>
	<modelVersion>4.0.0</modelVersion>
	<artifactId>rocketmq-consume-example</artifactId>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

4.4 the complete structure of the project is as follows:

5, Improve the rocketmq produce example project

5.1 add a profile


The configuration information is as follows:

logging.level.com.alibaba.cloud.stream.binder.rocketmq=DEBUG
# The address of the rocketmq server nameserver
spring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876

# stream->binding->output(input)
# output1
# Destination address for sending message
spring.cloud.stream.bindings.output1.destination=test-topic
# Default type of message
spring.cloud.stream.bindings.output1.content-type=application/json
# Producer group
spring.cloud.stream.rocketmq.bindings.output1.producer.group=binder-group
# Synchronous sending of messages
spring.cloud.stream.rocketmq.bindings.output1.producer.sync=true

# output2 is mainly used to send transaction messages
spring.cloud.stream.bindings.output2.destination=TransactionTopic
spring.cloud.stream.bindings.output2.content-type=application/json
# A transaction message was sent
spring.cloud.stream.rocketmq.bindings.output2.producer.transactional=true
spring.cloud.stream.rocketmq.bindings.output2.producer.group=myTxProducerGroup

# output3 uses it to manually pull messages
spring.cloud.stream.bindings.output3.destination=pull-topic
spring.cloud.stream.bindings.output3.content-type=text/plain
spring.cloud.stream.rocketmq.bindings.output3.producer.group=pull-binder-group

spring.application.name=rocketmq-produce-example

server.port=28081

management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

5.2 add an open class

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

5.3 adding MQSource


Define output in Source:

/**
* Read the output in our configuration file
*/
public interface MQSource {
	@Output("output1")
	MessageChannel output1() ;
	
	@Output("output2")
	MessageChannel output2() ;//Demonstrates the sending of transaction messages
	
	@Output("output1")
	MessageChannel output3() ;
}

4.5 add configuration class


The code is as follows:

@Configuration
@EnableBinding({MQSource.class})
public class MQConfig {
}

5.4 add a class to send messages

@Service
public class SendService {

	@Autowired
	private MQSource source;
	
	/**
	* Send a simple test message
	* @param msg
	* @throws Exception
	*/
	public void send(String msg) throws Exception {
	source.output1().send(MessageBuilder.withPayload(msg).build());
	}
	
	/**
	* Add tags when sending messages
	* @param msg
	* @param tag
	* @param <T>
	* @throws Exception
	*/
	public <T> void sendWithTags(T msg, String tag) throws Exception {
		Message message = MessageBuilder.createMessage(msg,
			new MessageHeaders(Stream.of(tag).collect(Collectors
				.toMap(str -> MessageConst.PROPERTY_TAGS,String::toString))));
		source.output1().send(message);
	}
	/**
	* Send an object message
	* @param msg
	* @param tag
	* @param <T>
	* @throws Exception
	*/
	public <T> void sendObject(T msg, String tag) throws Exception {
	Message message = MessageBuilder.withPayload(msg)
		.setHeader(MessageConst.PROPERTY_TAGS, tag)
		.setHeader(MessageHeaders.CONTENT_TYPE,MimeTypeUtils.APPLICATION_JSON)
		.build();
	source.output1().send(message);
	}
	/**
	* Send messages for transactions
	* @param msg
	* @param num
	* @param <T>
	* @throws Exception
	*/
	public <T> void sendTransactionalMsg(T msg, int num) throws Exception {
		MessageBuilder builder = MessageBuilder.withPayload(msg)
			.setHeader(MessageHeaders.CONTENT_TYPE,MimeTypeUtils.APPLICATION_JSON);
		builder.setHeader("test", String.valueOf(num));
		Message message = builder.build();
		source.output2().send(message);
	}
		public void sendMassiveMessage(String msg) {
			source.output3().send(MessageBuilder.withPayload(msg).build());
		}
}

5.6 transaction messages often require us to monitor and check back

Create a new class:


The code is as follows:

/**
* TransactionStatus.CommitTransaction: Message submission: when the message status is CommitTransaction, it means that consumers are allowed to consume the current message
* TransactionStatus.RollbackTransaction: Message rollback means that the MQ server will delete the current half message and consumers are not allowed to consume it.
* TransactionStatus.Unknown: Intermediate status indicates that the MQ service needs to initiate a backcheck operation to detect the execution status of the current sender's local transaction.
*/

@RocketMQTransactionListener(
	txProducerGroup = "myTxProducerGroup",
	corePoolSize = 5,
	maximumPoolSize = 10)
public class TransactionListenerImpl implements RocketMQLocalTransactionListener {
	/**
	*The message producer needs to execute the local transaction in the executelocal transaction. When the transaction half message is submitted successfully, the execution is completed
	After completion, you need to return the transaction status code.
	* @param msg
	* @param o
	* @return
	*/
	@Override
	public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object o)
	{
		Object num = msg.getHeaders().get("test");
		if ("1".equals(num)) {
			System.out.println(
				"executer: " + new String((byte[]) msg.getPayload()) + " unknown");
			return RocketMQLocalTransactionState.UNKNOWN; // This will cause the local transaction to be queried again
		}
		else if ("2".equals(num)) {
			System.out.println(
				"executer: " + new String((byte[]) msg.getPayload()) + " rollback");
			return RocketMQLocalTransactionState.ROLLBACK; // The semi message will be deleted by the mq server and the consumer will not consume the message
		}
		System.out.println(
			"executer: " + new String((byte[]) msg.getPayload()) + " commit");
		return RocketMQLocalTransactionState.COMMIT; // When a semi message is submitted, the consumer will consume the message.
	}

	/**
	* Implement the checkLocalTransaction method, which is used to check the local transaction execution and respond to the transaction status
	MQ My broker,
	* After execution, the corresponding transaction status code needs to be returned
	* @param message
	* @return
	*/
	@Override
	public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
		System.out.println("check: " + new String((byte[]) message.getPayload()));
		return RocketMQLocalTransactionState.COMMIT;
	}
}

5.7 build a simple model


The code is as follows:

5.8 sending of test message

@RestController
public class SendMessageController {
	
	@Autowired
	private SendService sendService ;
	
	/**
	* Send a simple message
	* @param msg
	* @return
	* @throws Exception
	*/
	@GetMapping("/send/simple")
	private ResponseEntity<String> sendSimpleMessage( @RequestParam(required = true)
	String msg) throws Exception {
		sendService.send(msg);
		return ResponseEntity.ok("Sent successfully") ;
	}
	/**
	* Send a message and tag it
	* @param msg news
	* @param tags Label of the message
	* @return
	* @throws Exception
	*/
	@GetMapping("/send/tags")
		private ResponseEntity<String> sendMessageWithTag( @RequestParam(required = true)
	String msg,@RequestParam(required = true)String tags) throws Exception {
		sendService.sendWithTags(msg,tags);
		return ResponseEntity.ok("Sent successfully") ;
	}
	/**
	* Send object message
	* @param user
	* @param tags
	* @return
	* @throws Exception
	*/
	@GetMapping("/send/object")
	public ResponseEntity<String> sendObjectMessage(User user,String tags) throws
	Exception {
		sendService.sendObject(user,tags);
		return ResponseEntity.ok("Sent successfully") ;
	}
	
	/**
	* Send a transaction message, that is, a half message
	* @param msg
	* @param num type
	* @return
	* @throws Exception
	*/
	@GetMapping("/send/transaction")
	public ResponseEntity<String> sendTransactionMessage(String msg ,int num) throws
	Exception {
		sendService.sendTransactionalMsg(msg,num);
		return ResponseEntity.ok("Sent successfully") ;
	}
/**
* Send a lot of messages
* @param msg
* @return
* @throws Exception
*/
@GetMapping("/send/poll")
public ResponseEntity<String> sendMassiveMessage(String msg) throws Exception {
	sendService.sendMassiveMessage(msg);
	return ResponseEntity.ok("Sent successfully") ;
	}
}

5.9 startup


The code is as follows:

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

6, Improve the rocketmq consumer example project

6.1 add profile


The contents are as follows:

# Address of rocketmq nameserver
spring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876

# stream->bindings->input
# input1
spring.cloud.stream.bindings.input1.destination=test-topic
spring.cloud.stream.bindings.input1.content-type=text/plain
spring.cloud.stream.bindings.input1.group=test-group1
spring.cloud.stream.rocketmq.bindings.input1.consumer.orderly=true

# input2
spring.cloud.stream.bindings.input2.destination=test-topic
spring.cloud.stream.bindings.input2.content-type=text/plain
spring.cloud.stream.bindings.input2.group=test-group2
spring.cloud.stream.rocketmq.bindings.input2.consumer.orderly=false
spring.cloud.stream.rocketmq.bindings.input2.consumer.tags=tagStr
spring.cloud.stream.bindings.input2.consumer.concurrency=20
spring.cloud.stream.bindings.input2.consumer.maxAttempts=1

# input3
spring.cloud.stream.bindings.input3.destination=test-topic
spring.cloud.stream.bindings.input3.content-type=application/json
spring.cloud.stream.bindings.input3.group=test-group3
spring.cloud.stream.rocketmq.bindings.input3.consumer.tags=tagObj
spring.cloud.stream.bindings.input3.consumer.concurrency=20

# input4
spring.cloud.stream.bindings.input4.destination=TransactionTopic
spring.cloud.stream.bindings.input4.content-type=text/plain
spring.cloud.stream.bindings.input4.group=transaction-group
spring.cloud.stream.bindings.input4.consumer.concurrency=5

# input5 manual message pull
spring.cloud.stream.bindings.input5.destination=pull-topic
spring.cloud.stream.bindings.input5.content-type=text/plain
spring.cloud.stream.bindings.input5.group=pull-topic-group

spring.application.name=rocketmq-consume-example

server.port=28082

management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

6.2 add a Sink


Add input in Sink:

public interface Sink {
	@Input("input1")
	SubscribableChannel input1();
	
	@Input("input2")
	SubscribableChannel input2();
	
	@Input("input3")
	SubscribableChannel input3();
	
	@Input("input4")
	SubscribableChannel input4();
	
	@Input("input5")
	PollableMessageSource input5();
}

6.3 creating listeners for messages

/**
* receive
*/
@Service
public class ReceiveService {

	@StreamListener("input1")
	public void receiveInput1(String receiveMsg) {
		System.out.println("input1 receive: " + receiveMsg);
	}
	
	@StreamListener("input2")
	public void receiveInput2(String receiveMsg) {
		System.out.println("input2 receive: " + receiveMsg);
	}
	
	@StreamListener("input3")
	public void receiveInput3(@Payload User user) {
		System.out.println("input3 receive: " + user);
	}
	
	@StreamListener("input4")
	public void receiveTransactionalMsg(String transactionMsg) {
		System.out.println("input4 receive transaction msg: " + transactionMsg);
	}
}

6.4 actively pull messages from mq server


Use scheduled tasks to actively pull messages from the server:

@Service
public class PullMessageTask {
	
	@Autowired
	private Sink sink ;
	
	@Scheduled(fixedRate = 5*1000)
	public void pullMessage(){
		sink.input5().poll((message) -> {
			String payload = (String) message.getPayload();
			System.out.println("pull msg: " + payload);
		}, new ParameterizedTypeReference<String>() {
		});
	}
}

6.5 model class

Copy directly from the production:

6.6 configuration class

New MQConfig:

The code is as follows:

@Configuration
@EnableBinding({Sink.class})
public class MQConfig {
}

6.7 startup

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

7, Test case test

7.1 start service

Start 2 services:

  • rocketmq-produce-example
  • rocketmq-consumer-example

7.2 sending message test

7.2.1 sending simple strings

http://localhost:28081/send/simple?msg=RocketMQ

7.2.2 sending tagged messages

7.2.3 sending object message

http://localhost:28081/send/object?id=1&userName=bjsxt&password=123456&tags=xxx

7.2.4 sending transaction messages

http://localhost:28081/send/transaction?msg=order&num=1

http://localhost:28081/send/transaction?msg=order&num=2

http://localhost:28081/send/transaction?msg=order&num=3

7.2.4 manually pull messages

http://localhost:28081/send/poll?msg=order

Topics: Zookeeper Back-end Distribution Spring Cloud rpc