Messaging middleware --RabbitMQ (eleven) RabbitMQ integrate Spring Cloud Stream combat! (all)

Seeking attention
RabbitMQ integrate Spring Cloud Stream combat!

Foreword

1. SpringCloudStream integration

  • Spring Cloud, this family bucket framework throughout the small and medium sized Internet companies unusual hot, then the corresponding Spring Cloud Stream will gradually be everyone pay attention to it, the main lesson to describe how Spring Cloud Stream to integrate with RabbitMQ.

Architecture Introduction

Chart

Destination Binder: Application Application contains its own is left RabbitMQ, the right is Kafka. Production and represents message transmission, the message may be different middleware. This is the Spring Cloud Stream the top of an abstract. Very good place.

Spring Cloud Stream core architecture 1

Two important areas: inputs (input) message receiving terminal, Outputs (output) end of a message sent Spring Cloud Stream applied to core messaging middleware, applications Spring Cloud Stream injected through input / output channel to communicate with the outside channels . Binder achieved through specific channels to communicate with an external messaging middleware.

Spring Cloud Stream Core 2 architecture

Yellow : represents RabbitMQ Green : input and output plug, a layer of the message are set plug, the plug can be used for a variety of different message can also be used to replace the message middleware.

Core concepts: Barista接口 : Barista interfaces is defined as a parameter back class interface definition for this type of channel and the channel name, the channel name is used as a configuration, the channel type determines the channel app will use this message is transmitted from or received messages.

How to define the channel interface: @Output: output annotation that defines the interface to send a message @Input: annotation input, for defining a message consumer interfaces @StreamListener: for annotation defines listener methods

Use Spring Cloud Stream is very simple, just use good these three notes can be very appropriate in the scene to achieve the production and consumption of high-performance message, but using SpringCloudStream framework has a very big problem that they can not achieve reliability of delivery 100% reliability, which is not guaranteed message, there will be a small amount of message loss problems. Currently SpringCloudStream integration of RabbitMQ and Kafka, we all know that Kafka was unable to deliver the message reliability, the reason is because SpringCloudStream framework for both Kafka and so the purpose of using it in practical work is aimed at high-performance message communication! This point is located at the current version of SpringCloudStream. Therefore, in the actual work, may be employed SpringCloudStream, if necessary to ensure the reliability of delivery, may be used alone RabbitMQ, it is also possible.

2. The code demonstrates

2.1 Production end

2.1.1 Creating rabbitmq-springcloudstream-producer project

1, pom.xml dependency is introduced


<?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">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.cp</groupId>
	<artifactId>rabbitmq-springcloudstream-producer</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>rabbitmq-springcloudstream-producer</name>
	<description>rabbitmq-spring</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.8.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>	
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-autoconfigure</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		
		<dependency>
		    <groupId>org.springframework.cloud</groupId>
		    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
		    <version>1.3.4.RELEASE</version>
		</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>


复制代码

2, the interface is defined Barista


/**
 * 这里的Barista接口是定义来作为后面类的参数,这一接口定义来通道类型和通道名称。
 * 通道名称是作为配置用,通道类型则决定了app会使用这一通道进行发送消息还是从中接收消息。
 */
public interface Barista {
	  
    String OUTPUT_CHANNEL = "output_channel";  
    //注解@Output声明了它是一个输出类型的通道,名字是output_channel。这一名字与app1中通道名一致,表明注入了一个名字为output_channel的通道,类型是output,发布的主题名为mydest。  
    @Output(Barista.OUTPUT_CHANNEL)
    MessageChannel logoutput();  
}  

复制代码

3, the definition of class RabbitmqSender


//启动这个绑定
@EnableBinding(Barista.class)
@Service //注入到spring容器  
public class RabbitmqSender {  
  
	//注入Barista
    @Autowired  
    private Barista barista;  
    
    // 发送消息
    public String sendMessage(Object message, Map<String, Object> properties) throws Exception {  
        try{
        	MessageHeaders mhs = new MessageHeaders(properties);
        	Message msg = MessageBuilder.createMessage(message, mhs);
            boolean sendStatus = barista.logoutput().send(msg);
            System.err.println("--------------sending -------------------");
            System.out.println("发送数据:" + message + ",sendStatus: " + sendStatus);
        }catch (Exception e){  
        	System.err.println("-------------error-------------");
        	e.printStackTrace();
            throw new RuntimeException(e.getMessage());
           
        }  
        return null;
    }  
    
}  

复制代码

4、application.properties


server.port=8001
server.servlet.context-path=/producer

spring.application.name=producer
spring.cloud.stream.bindings.output_channel.destination=exchange-3
## group相当于RabbitMQ中Queue的名称
spring.cloud.stream.bindings.output_channel.group=queue-3

##以下为集群环境配置,rabbit_cluster与下面的spring.cloud.stream.binders.rabbit_cluster是对应的。
spring.cloud.stream.bindings.output_channel.binder=rabbit_cluster

spring.cloud.stream.binders.rabbit_cluster.type=rabbit
spring.cloud.stream.binders.rabbit_cluster.environment.spring.rabbitmq.addresses=localhost:5672
spring.cloud.stream.binders.rabbit_cluster.environment.spring.rabbitmq.username=user_cp
spring.cloud.stream.binders.rabbit_cluster.environment.spring.rabbitmq.password=123456
spring.cloud.stream.binders.rabbit_cluster.environment.spring.rabbitmq.virtual-host=/vhost_cp

复制代码

2.1 Consumer end

1, pom.xml dependency is introduced


<?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">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.cp</groupId>
	<artifactId>rabbitmq-springcloudstream-consumer</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>rabbitmq-springcloudstream-consumer</name>
	<description>rabbitmq-spring</description>
 
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.8.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>	
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
		    <groupId>org.springframework.cloud</groupId>
		    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
		    <version>1.3.4.RELEASE</version>
		</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>


复制代码

2, the interface is defined Barista


/**
 * 这里的Barista接口是定义来作为后面类的参数,这一接口定义来通道类型和通道名称。
 * 通道名称是作为配置用,通道类型则决定了app会使用这一通道进行发送消息还是从中接收消息。
 */

public interface Barista {
	  
    String INPUT_CHANNEL = "input_channel";  

    //注解@Input声明了它是一个输入类型的通道,名字是Barista.INPUT_CHANNEL,也就是position3的input_channel。这一名字与上述配置app2的配置文件中position1应该一致,表明注入了一个名字叫做input_channel的通道,它的类型是input,订阅的主题是position2处声明的mydest这个主题  
    @Input(Barista.INPUT_CHANNEL)  
    SubscribableChannel loginput();  
    
      
}  

复制代码

3, the definition of class RabbitmqReceiver


//启动binding
@EnableBinding(Barista.class)
@Service
public class RabbitmqReceiver {  

	
    @StreamListener(Barista.INPUT_CHANNEL)  
    public void receiver(Message message) throws Exception {  
		
    	//手工签收必须要有channel与deliveryTag
    	Channel channel = (com.rabbitmq.client.Channel) message.getHeaders().get(AmqpHeaders.CHANNEL);
		Long deliveryTag = (Long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
    	System.out.println("Input Stream 1 接受数据:" + message);
    	System.out.println("消费完毕------------");
    	//批量签收设置为false
    	channel.basicAck(deliveryTag, false);
    }  
}

复制代码

4、application.properties


server.port=8002
server.context-path=/consumer

spring.application.name=consumer
spring.cloud.stream.bindings.input_channel.destination=exchange-3
spring.cloud.stream.bindings.input_channel.group=queue-3
spring.cloud.stream.bindings.input_channel.binder=rabbit_cluster
##默认监听数
spring.cloud.stream.bindings.input_channel.consumer.concurrency=1
##针对消费端channel进行设置,是否支持requeue,重回队列
spring.cloud.stream.rabbit.bindings.input_channel.consumer.requeue-rejected=false
##是否支持签收,签收模式:手工签收
spring.cloud.stream.rabbit.bindings.input_channel.consumer.acknowledge-mode=MANUAL
##服务重连
spring.cloud.stream.rabbit.bindings.input_channel.consumer.recovery-interval=3000
##是否持久化订阅
spring.cloud.stream.rabbit.bindings.input_channel.consumer.durable-subscription=true


##最大监听数
spring.cloud.stream.rabbit.bindings.input_channel.consumer.max-concurrency=5

##采用rabbitmq方式,也可以采用kafka
spring.cloud.stream.binders.rabbit_cluster.type=rabbit
spring.cloud.stream.binders.rabbit_cluster.environment.spring.rabbitmq.addresses=localhost:5672
spring.cloud.stream.binders.rabbit_cluster.environment.spring.rabbitmq.username=user_cp
spring.cloud.stream.binders.rabbit_cluster.environment.spring.rabbitmq.password=123456
spring.cloud.stream.binders.rabbit_cluster.environment.spring.rabbitmq.virtual-host=/vhost_cp

复制代码

3. Run the test

3.1 Running the consumer side

After starting the project, view the control station is generated and Exchange Queue

Exchange
Queue

After starting the project, SpringCloudStream generated Exchange and Queue.

Production end test code running 3.2


@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {

	@Autowired
	private RabbitmqSender rabbitmqSender;
	
	
	@Test
	public void sendMessageTest1() throws InterruptedException {
       for(int i = 0; i < 1; i ++){
    	   try {
		       Map<String, Object> properties = new HashMap<String, Object>();
		       properties.put("SERIAL_NUMBER", "12345");
		       properties.put("BANK_NUMBER", "abc");
		       properties.put("PLAT_SEND_TIME", DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss.SSS"));
	    	   rabbitmqSender.sendMessage("Hello, I am amqp sender num :" + i, properties);
              
           } catch (Exception e) {
        	   System.out.println("--------error-------");
               e.printStackTrace(); 
           }
       }
       TimeUnit.SECONDS.sleep(2000);
	}
	
}


复制代码

Running the test method: sendMessageTest1 (), see the printed results.

End print production results:

End print production results

Consumer-side printing results:

Consumer-side printing results

summary

By these chapters, we learned knowledge of Spring AMQP through learning, we inherit Spring RabbitMQ team has an in-depth understanding, so for our follow-up study, the use of work have laid a solid foundation, and finally we integrate SpringBoot and SpringCloudStream, more convenient and more efficient integrated into our apps go! Three chunks of learning, learning the RabbitMQ, statement messages, message templates, SimpleMessageListenerContainer, MessageListenerAdapter, MessageConverter. Support String converter, Json converter, convert Java objects, multiple objects conversion, flow conversion (pictures, documents). Integration with SpringBoot very, very simplified, only a few can be configured to send and receive messages. Add a layer of a multi-agency input and output on SpringCloudStream nature. To replace the MQ later, the channel level code can not be modified. The production side may be RabbitMQ, the consumer side is Kafka.

The end of the sentence

Welcome attention to personal micro-channel public number: Coder program for the latest original technical articles and free learning materials, a lot more boutique mind maps, interview data, PMP preparation materials waiting for you to lead, allowing you to learn technical knowledge anytime, anywhere! Create a qq group: 315 211 365, we welcome into the group exchange study together. Thank you! Can also be introduced to the side of a friend in need.

Articles included to Github: github.com/CoderMerlin... Gitee: gitee.com/573059382/c... welcome attention and star ~

Micro-channel public number

Messaging middleware --RabbitMQ (eight) advanced features all here! (At)

Messaging middleware --RabbitMQ (nine) RabbitMQ integrate Spring AMQP combat! (all)

Messaging middleware --RabbitMQ (ten) RabbitMQ integration SpringBoot combat! (all)

Guess you like

Origin juejin.im/post/5d65e58de51d453b5f1a04b6