RabbitMQ:一般集群模式下的测试以及问题的发现

1.声明

当前内容主要用于本人学习和复习之用,内容包括探讨一般集群模式下的测试,发现其中的问题

节点名称节点ip
node1192.168.1.110
node2192.168.1.108
node3192.168.1.102

启动后的页面
在这里插入图片描述

2.测试集群消费

1.创建队列和交换exchange(在node)

public class ClusterNode2MsgSender {
	private static String host = "192.168.1.108";
	private static int port = 5672;
	private static String username = "root";
	private static String password = "root";
	// private static String vhost = "/";

	public static void main(String[] args) throws IOException {
		RabbitMqUtils mqUtils = new RabbitMqUtils(host, port, username, password);
		String exchangeName = "node2Exchange";
		 String queueName = "node2Queue";
		try (Connection connection = mqUtils.getConnection(); Channel channel = connection.createChannel();) {

			DeclareOk declareOk = channel.exchangeDeclare(exchangeName, BuiltinExchangeType.TOPIC, true, false, null);
			System.out.println("创建【" + exchangeName + "】的exchange成功==>" + declareOk);
			com.rabbitmq.client.AMQP.Queue.DeclareOk declareOk2 = channel.queueDeclare(queueName, true, false, false,
					null);
			System.out.println("创建【" + queueName + "】的queu成功==>" + declareOk2);

			BindOk bindOk = channel.queueBind(queueName, exchangeName, "test");
			System.out.println("绑定queue到exchange成功==>" + bindOk);

		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}

结果:
在这里插入图片描述
所有的ui界面结果
在这里插入图片描述
2.创建生产者(分别向node1、node2、node3中的node3Exchange中发送消息)

node1的生产者

public class ClusterNode1MsgSender {
	private static String host = "192.168.1.110";
	private static int port = 5672;
	private static String username = "root";
	private static String password = "root";
	// private static String vhost = "/";

	public static void main(String[] args) throws IOException {
		RabbitMqUtils mqUtils = new RabbitMqUtils(host, port, username, password);
		String exchangeName = "node2Exchange";
		try (Connection connection = mqUtils.getConnection();
				Channel channel = connection.createChannel();) {

			BasicProperties.Builder builder=new BasicProperties.Builder();
			builder.deliveryMode(2);
			BasicProperties props = builder.build();
			for (int i = 0; i < 10; i++) {
				channel.basicPublish(exchangeName, "test", props, ("【" + (i + 1) + "】node1,你好集群").getBytes());
			}
		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}

node2生产者

public class ClusterNode2MsgSender {
	private static String host = "192.168.1.108";
	private static int port = 5672;
	private static String username = "root";
	private static String password = "root";
	// private static String vhost = "/";

	public static void main(String[] args) throws IOException {
		RabbitMqUtils mqUtils = new RabbitMqUtils(host, port, username, password);
		String exchangeName = "node2Exchange";

		try (Connection connection = mqUtils.getConnection(); Channel channel = connection.createChannel();) {

			BasicProperties.Builder builder = new BasicProperties.Builder();
			builder.deliveryMode(2);
			BasicProperties props = builder.build();

			for (int i = 0; i < 10; i++) {
				channel.basicPublish(exchangeName, "test", props, ("【" + (i + 1) + "】node2,你好集群").getBytes());
			}

		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}

node3生产者

public class ClusterNode3MsgSender {
	private static String host = "192.168.1.102";
	private static int port = 5672;
	private static String username = "root";
	private static String password = "root";
	// private static String vhost = "/";

	public static void main(String[] args) throws IOException {
		RabbitMqUtils mqUtils = new RabbitMqUtils(host, port, username, password);
		String exchangeName = "node2Exchange";
		try (Connection connection = mqUtils.getConnection();
				Channel channel = connection.createChannel();) {
		
			BasicProperties.Builder builder=new BasicProperties.Builder();
			builder.deliveryMode(2);
			BasicProperties props = builder.build();
		
			
			for (int i = 0; i < 10; i++) {
				channel.basicPublish(exchangeName, "test", props, ("【" + (i + 1) + "】node3,你好集群").getBytes());
			}
		} catch (TimeoutException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}

3.创建node2节点的node2Queue的消费者

public class ClusterNode2MsgComsumer {
	private static String host = "192.168.1.108";
	private static int port = 5672;
	private static String username = "root";
	private static String password = "root";

	public static void main(String[] args) throws IOException {
		RabbitMqUtils mqUtils = new RabbitMqUtils(host, port, username, password);
		String queueName = "node2Queue";
		Connection connection = mqUtils.getConnection();
		Channel channel = connection.createChannel();
		channel.basicConsume(queueName, true, new DefaultConsumer(channel) {

			@Override
			public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
					throws IOException {
				System.out.println("consumerTag==>" + consumerTag);
				System.out.println("envelope==>" + envelope);
				System.out.println("props==>" + properties);
				System.out.println("消费者node2接收消息==>【" + StringUtils.toString(body) + "】");
			}

		});

	}
}

4.分别启动所有的生产者

在这里插入图片描述

5.启动一个node2消费者
在这里插入图片描述
测试成功

3.查看和测试node2Queue

分析发现node2Queue属于node2节点的
在这里插入图片描述

直接将该节点node2直接stop_app
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
再次启动生产者

此时发现除了node2的消息发送直接出现错误,其他的node1和node2都不会出现报错

再次启动消费者
在这里插入图片描述
修改消费者ip为其他的node3的ip的时候,前面一样直接报错

private static String host = "192.168.1.102";

在这里插入图片描述
发现一旦当前的主要存储消息的node2节点宕机,那么其他的节点接收到同样发向node2的节点的时候不会有任何问题(不报错),然而直接发向node2节点的直接报错

再次启动node2节点,查看消息是否丢失
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
发现此时消息都丢失了,这说明如果出现无法连接到写入的节点的时候,其他节点接收的消息直接丢弃(存在消息丢失的问题)

并且发现此时可以通过node3连接到node2Queue节点!

4.分析集群中存在的问题

  1. 集群中正常的时候
    1.1. 任何客户端都可以通过任何的节点去连接一个节点中的队列,此时不会出现问题
    1.2. 向任何节点中的Exchange推送消息的时候,都会被转发到指定路由节点的队列中

  2. 当集群中节点(存放数据的节点)宕机的时候
    1.1 该消费者不能通过任何节点去连接该宕机节点的队列,此时连接会报错的
    1.2 向宕机节点推送数据直接报错,无法推送数据;向其他没有宕机节点发送指向宕机节点的数据时候,不会出现报错,而是出现直接丢弃数据(可以设置返回)

所以集群中的模式应该是这样的

1.(集群正常)发布数据到node2Queue中
在这里插入图片描述
2.(集群中node2出现宕机)发布数据到node2Queue中
在这里插入图片描述
所以无法向node2中发送数据(连接都报错了),而连接node1、node3却可以

3.(集群正常)拉取消息
在这里插入图片描述

4.(集群中node2出现宕机)拉取消息
在这里插入图片描述
所以一旦拉取宕机节点的队列的数据的时候,所有的其他的node都是同样的报错

5.总结

1.集群环境下的rabbitmq带来了好处,就是可以通过任意节点获取指定的队列中的数据(但是需要指定节点)

2.集群环境下的rabbitmq也同样带来了坏处,如果一个节点宕机,那么不能通过任何一个节点访问该宕机节点的队列,但是可以向没有宕机的节点访问该宕机节点的队列

3.集群中数据实际是存放在一个节点中的,该实际存放数据的节点可能导致其他的问题

4.只要能解决上面的问题:数据节点宕机问题,保证消息可达,保证消息能正常在集群中消费等问题那么集群就不存在问题

5.为什么不能通过一个代理例如:eureka注册中心方式直接注册rabbitmq,通过一个节点就可操作了,为什么还要指定ip,每次创建queue的时候都直接和节点绑定了,不利于分布式

以上纯属个人见解,如有问题请联本人!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值