1.声明
当前内容主要用于本人学习和复习,当前内容为使用SpringBoot测试RabbitMQ集群
当前集群:
节点 | 节点ip |
---|---|
node2 | 192.168.1.104 |
node3 | 192.168.1.107 |
2.编写SpringBoot程序
pom依赖
<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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath />
</parent>
<groupId>SpringBoot-RabbitMQClusters</groupId>
<artifactId>SpringBoot-RabbitMQClusters</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>SpringBoot-RabbitMQClusters</name>
<url>http://maven.apache.org</url>
<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>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
1.编写配置文件:
server.port=8080
spring.rabbitmq.addresses=192.168.1.104:5672,192.168.1.107:5672
spring.rabbitmq.username=root
spring.rabbitmq.password=root
2.编写RabbitMQ配置类
/**
* @description 主动创建一个rabbitMQ集群的配置类(需要手动使用ha模式)
* @author hy
* @date 2020-05-31
*/
@Configuration
public class RabbitMQClusterConfig {
/*
* @Autowired RabbitTemplate rabbitTemplate;
*
* @Autowired AmqpTemplate amqpTemplate;
*/
public static final String QUEUE_NAME = "node3Queue";
public static final String EXCHANGE_NAME="testExchange";
// 创建持久化的node3Queue
@Bean
Queue queue() {
return QueueBuilder.durable(QUEUE_NAME).build();
}
// 创建持久化的testExchange
@Bean
org.springframework.amqp.core.Exchange exchange() {
return ExchangeBuilder.directExchange(EXCHANGE_NAME).durable(true).build();
}
// 创建绑定
@Bean
Binding bindings(){
return BindingBuilder.bind(queue()).to(exchange()).with("").and(null);
}
}
3.编写controller层
/**
* @description 消息controller层
* @author hy
* @date 2020-05-31
*/
@RestController
public class MsgController {
@Autowired
AmqpTemplate amqpTemplate;
@RequestMapping("/send")
public String sendMsg(String msg) {
// 发布持久化消息
MessageProperties props = MessagePropertiesBuilder.newInstance().setDeliveryMode(MessageDeliveryMode.fromInt(2))
.build();
Message message = new Message(msg == null ? "".getBytes() : msg.getBytes(), props);
amqpTemplate.convertAndSend(RabbitMQClusterConfig.EXCHANGE_NAME, "", message);
return "发送消息【" + msg + "】成功!";
}
@RequestMapping("/get")
public String getMsg() throws UnsupportedEncodingException {
// 发布持久化消息
Object message = amqpTemplate.receiveAndConvert(RabbitMQClusterConfig.QUEUE_NAME,2000l);
if(message==null) {
return "没有任何数据";
}
String msg = null;
if (message instanceof Message) {
msg = new String(((Message) message).getBody(), "utf-8");
}
msg = new String((byte[])message, "utf-8");
return "接收消息【" + msg + "】成功!";
}
}
创建入口类
/**
* @description 使用SpringBoot简单的访问RabbitMQ,注册成功
* @author hy
* @date 2020-05-31
*/
@RestController
@SpringBootApplication
public class RabbitMQApplication {
public static void main(String[] args) {
SpringApplication.run(RabbitMQApplication.class, args);
}
}
3.启动并测试SpringBoot程序
1.测试发送数据:http://localhost:8080/send?msg=你好集群
控制台结果:
此时发现当前的SpringBoot就是启动了一个连接,一个基于tcp协议的连接
2.测试接收消息:http://localhost:8080/get
3.测试发送多次消息
http://localhost:8080/send?msg=你好集群1
http://localhost:8080/send?msg=你好集群2
http://localhost:8080/send?msg=你好集群3
此时发现当前的控制台中没有任何的连接显示,这说明springboot实际上是使用同一个uri进行连接的(只打开一个)
4.将node2节点宕机
此时控制台显示
发现连接重置,和出现了shutdown回调
5.此时将node2启动将node3宕机
再次发送消息,和接收消息,发现此时不能发送消息,因为节点node3是集群主节点,但是为什么不能连接node2,这就说明了SpringBoot操作集群的问题
4.发现问题
- 使用springboot默认是一个连接到节点中的,如果该节点不宕机,那么会一直使用这个节点连接操作(导致该节点的压力过大)
- 使用这种配置将所有的节点目的地的ip都暴露出来了
- 使用这种方式的时候如果,主节点宕机那么会导致所有的节点都不可用(整个集群问题)
- 这就是为什么需要使用haproxy来实现,因为haproxy是负载均衡模式的(并且只暴露一个ip地址)
5.测试启动haproxy模式后的结果
1.启动haproxy(haproxy配置在192.168.1.103端口)
此时发现当前的节点node3还是宕机状态
2.修改当前的application.properties的配置
spring.rabbitmq.addresses=192.168.1.103:5672
3.再次启动测试
测试获取数据
此时发现haproxy模式可以很好的处理当前SpringBoot配置多个RabbitMQ的ip的问题,并且使用负载均衡策略
6.总结
1.使用SpringBoot直接操作集群需要注意一个问题,那就是主节点宕机后,导致所有RabbitMQ不可用,并且是按照一个宕机才会去连接下一个,容易导致一个节点压力过大的问题
2.使用haproxy操作的时候就不会存在这个问题,所以建议使用haproxy或者keepalived模式,让springboot只操作一个端口