2024.2.29 模拟实现 RabbitMQ —— 项目展示

目录

项目介绍

核心功能

核心技术

演示直接交换机

演示扇出交换机

演示主题交换机


项目介绍

  • 此处我们模拟 RabbitMQ 实现了一个消息队列服务器

核心功能

  • 提供了 虚拟主机交换机队列绑定消息 概念的管理
  • 九大核心 API 创建队列销毁队列创建交换机销毁交换机创建绑定解除绑定发布消息订阅消息确认消息
  • 实现了三种典型的消息转换方式 直接交换机(Direct)扇出交换机(Fanout)主题交换机(Topic)
  • 交换机队列绑定 使用 SQLite 数据库持久化,消息 使用文件持久化
  • 基于 TCP + 自定义应用层协议 实现生产者/消费者和 Broker Server 之间的交互工作

核心技术

  • Spring Boot / MyBatis / Lombok
  • SQLite
  • TCP

  • 关于该项目的需求分析,可点击下方链接跳转

模拟实现 RabbitMQ —— 需求分析


  • 关于该项目的核心类,可点击下方链接跳转

模拟实现 RabbitMQ —— 实现核心类


  • 关于该项目的数据库操作,可点击下方链接跳转

模拟实现 RabbitMQ —— 数据库操作


  • 关于该项目的消息持久化,可点击下方链接跳转

模拟实现 RabbitMQ —— 消息持久化


  • 关于该项目的内存数据管理,可点击下方链接跳转

模拟实现 RabbitMQ —— 内存数据管理


  • 关于该项目的虚拟机设计,可点击下方链接跳转

模拟实现 RabbitMQ —— 虚拟主机设计


  • 关于该项目的交换机转发规则,可点击下方链接跳转

模拟实现 RabbitMQ —— 实现转发规则


  • 关于该项目的消费逻辑,可点击下方链接跳转

模拟实现 RabbitMQ —— 实现消费消息逻辑


  • 关于该项目网络通信设计,可点击下方链接跳转

模拟实现 RabbitMQ —— 网络通信设计(服务器)

模拟实现 RabbitMQ —— 网络通信设计(客户端)

演示直接交换机

  • 简单写一个 demo 模拟 跨主机的生产者消费者模型
  • 此处为了方便,就在本机演示

  • 此处我们创建的交换机类型为 直接交换机

1、在 Spring Boot 项目的启动类中创建 Broker Server,绑定端口并启动!

@SpringBootApplication
public class DemoApplication {
	public static ConfigurableApplicationContext context;

	public static void main(String[] args) throws IOException {
		context = SpringApplication.run(DemoApplication.class, args);

		BrokerServer brokerServer = new BrokerServer(9090);
		brokerServer.start();
	}
}

2、编写生产者代码

/*
* 这个类用来表示一个生产着
* 通常这是一个单独的服务器程序
* */
public class DemoProducer {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("启动生产者!");
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        connectionFactory.setPort(9090);

        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();

//        创建交换机和队列
        channel.exchangeDeclare("testExchange", ExchangeType.DIRECT,true,false,null);
        channel.queueDeclare("testQueue",true,false,false,null);

//        创建一个消息并发送
        byte[] body = "hello".getBytes();
        boolean ok = channel.basicPublish("testExchange","testQueue",null,body);
        System.out.println("消息投递完成! ok = " + ok);

        Thread.sleep(500);
        channel.close();
        connection.close();
    }
}

3、编写消费者代码

/*
* 这个类表示一个消费者
* 通常这个类也应该是在一个独立的服务器中被执行
* */
public class DemoConsumer {
    public static void main(String[] args) throws IOException, InterruptedException, MqException {
        System.out.println("启动消费者!");
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        connectionFactory.setPort(9090);

        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();

        channel.exchangeDeclare("testExchange",ExchangeType.DIRECT,true,false,null);
        channel.queueDeclare("testQueue",true,false,false,null);

        channel.basicConsume("testQueue", true, new Consumer() {
            @Override
            public void handleDelivery(String consumerTag, BasicProperties basicProperties, byte[] body) throws MqException, IOException {
                System.out.println("[消费数据] 开始!");
                System.out.println("consumerTag = " + consumerTag);
                System.out.println("basicProperties = " + basicProperties);
                String bodyString = new String(body,0,body.length);
                System.out.println("body = " + bodyString);
                System.out.println("[消费数据] 结束!");
            }
        });

//        由于消费者也不知道生产者要生产多少消息,就在这里通过这个循环模拟一直等待消费
        while (true) {
            Thread.sleep(500);
        }
    }
}

4、启动 Spring Boot 项目(启动 Broker Server)


5、运行消费者代码


6、运行生产者代码


7、继续观察消费者的控制台

演示扇出交换机

  • 此处我们创建的交换机类型为 扇出交换机

 1、编写生产者代码

/*
 * 这个类用来表示一个生产着
 * 通常这是一个单独的服务器程序
 * */
public class DemoProducer {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("启动生产者!");
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        connectionFactory.setPort(9090);

        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
//        创建交换机
        channel.exchangeDeclare("testExchange", ExchangeType.FANOUT,true,false,null);
//        创建一个消息并发送
        byte[] body = "hello".getBytes();
        boolean ok = channel.basicPublish("testExchange","",null,body);
        System.out.println("消息投递完成! ok = " + ok);

        Thread.sleep(500);
        channel.close();
        connection.close();
    }
}

3、编写消费者A 代码

/*
 * 这个类表示一个消费者A
 * 通常这个类也应该是在一个独立的服务器中被执行
 * */
public class DemoConsumerA {
    public static void main(String[] args) throws IOException, InterruptedException, MqException {
        System.out.println("启动消费者!");
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        connectionFactory.setPort(9090);

        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
//        创建交换机
        channel.exchangeDeclare("testExchange",ExchangeType.FANOUT,true,false,null);
//        创建队列
        channel.queueDeclare("testQueue1",true,false,false,null);
//        设置绑定
        channel.queueBind("testQueue1","testExchange","");
//        订阅消息
        channel.basicConsume("testQueue1", true, new Consumer() {
            @Override
            public void handleDelivery(String consumerTag, BasicProperties basicProperties, byte[] body) throws MqException, IOException {
                System.out.println("[testQueue1 消费数据] 开始!");
                System.out.println("consumerTag = " + consumerTag);
                System.out.println("basicProperties = " + basicProperties);
                String bodyString = new String(body,0,body.length);
                System.out.println("body = " + bodyString);
                System.out.println("[testQueue1 消费数据] 结束!");
            }
        });

//        由于消费者也不知道生产者要生产多少消息,就在这里通过这个循环模拟一直等待消费
        while (true) {
            Thread.sleep(500);
        }
    }
}

4、编写消费者B 代码

/*
 * 这个类表示一个消费者B
 * 通常这个类也应该是在一个独立的服务器中被执行
 * */
public class DemoConsumerB {
    public static void main(String[] args) throws IOException, InterruptedException, MqException {
        System.out.println("启动消费者!");
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        connectionFactory.setPort(9090);

        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
//        创建交换机
        channel.exchangeDeclare("testExchange", ExchangeType.FANOUT,true,false,null);
//        创建队列
        channel.queueDeclare("testQueue2",true,false,false,null);
//        设置绑定
        channel.queueBind("testQueue2","testExchange","");
//        订阅消息
        channel.basicConsume("testQueue2", true, new Consumer() {
            @Override
            public void handleDelivery(String consumerTag, BasicProperties basicProperties, byte[] body) throws MqException, IOException {
                System.out.println("[testQueue1 消费数据] 开始!");
                System.out.println("consumerTag = " + consumerTag);
                System.out.println("basicProperties = " + basicProperties);
                String bodyString = new String(body,0,body.length);
                System.out.println("body = " + bodyString);
                System.out.println("[testQueue1 消费数据] 结束!");
            }
        });

//        由于消费者也不知道生产者要生产多少消息,就在这里通过这个循环模拟一直等待消费
        while (true) {
            Thread.sleep(500);
        }
    }
}

5、启动 Spring Boot 项目(启动 Broker Server)


6、运行消费者A 代码


7、运行消费者B 代码


8、运行生产者代码


9、继续观察消费者A 的控制台


10、继续观察消费者B 的控制台

演示主题交换机

  • 此处我们创建的交换机为 主题交换机

 1、编写生产者代码

/*
 * 这个类用来表示一个生产着
 * 通常这是一个单独的服务器程序
 * */
public class DemoProducer {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("启动生产者!");
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        connectionFactory.setPort(9090);

        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();

//        创建交换机和队列
        channel.exchangeDeclare("testExchange", ExchangeType.TOPIC,true,false,null);
        channel.queueDeclare("testQueue",true,false,false,null);

//        创建消息A 并发送
        byte[] body = "hello".getBytes();
        boolean ok = channel.basicPublish("testExchange","ccc.aaa.bbb",null,body);
        System.out.println("消息投递完成! ok = " + ok);

//        创建消息B 并发送
        body = "hi".getBytes();
        ok = channel.basicPublish("testExchange","aaa.bbb",null,body);
        System.out.println("消息投递完成! ok = " + ok);

        Thread.sleep(500);
        channel.close();
        connection.close();
    }
}

3、编写消费者代码

/*
 * 这个类表示一个消费者
 * 通常这个类也应该是在一个独立的服务器中被执行
 * */
public class DemoConsumer {
    public static void main(String[] args) throws IOException, InterruptedException, MqException {
        System.out.println("启动消费者!");
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        connectionFactory.setPort(9090);

        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
//        创建交换机
        channel.exchangeDeclare("testExchange", ExchangeType.TOPIC,true,false,null);
//        创建队列
        channel.queueDeclare("testQueue",true,false,false,null);
//        设置绑定
        channel.queueBind("testQueue","testExchange","*.aaa.bbb");
//        订阅消息
        channel.basicConsume("testQueue", true, new Consumer() {
            @Override
            public void handleDelivery(String consumerTag, BasicProperties basicProperties, byte[] body) throws MqException, IOException {
                System.out.println("[消费数据] 开始!");
                System.out.println("consumerTag = " + consumerTag);
                System.out.println("basicProperties = " + basicProperties);
                String bodyString = new String(body,0,body.length);
                System.out.println("body = " + bodyString);
                System.out.println("[消费数据] 结束!");
            }
        });
//        由于消费者也不知道生产者要生产多少消息,就在这里通过这个循环模拟一直等待消费
        while (true) {
            Thread.sleep(500);
        }
    }
}

4、启动 Spring Boot 项目(启动 Broker Server)


5、运行消费者代码


6、运行生产者代码


7、继续观察消费者的控制台

  • 24
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

茂大师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值