RabbitMQ五大常用工作模式

这篇具有很好参考价值的文章主要介绍了RabbitMQ五大常用工作模式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.简单队列

RabbitMQ五大常用工作模式,RabbitMQ,rabbitmq

  • 消息生产者

    public class Send {
        private static final String QUEUE_NAME = "hello";
    
        public static void main(String[] args) throws Exception {
            // 连接工厂
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("192.168.101.128");
            factory.setPort(5672);
            factory.setUsername("admin");
            factory.setPassword("Gen123");
            factory.setVirtualHost("/");
    
            try (Connection connection = factory.newConnection();
                 Channel channel = connection.createChannel()) {
                // 声明队列
                channel.queueDeclare(QUEUE_NAME, false, false, false, null);
                String message = "这是一条消息!!!";
                // 发送消息
                channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));
                System.out.println("Send:" + message);
            }
        }
    }
    
  • 消息消费者(会一直监听队列)

    public class Recv {
        private static final String QUEUE_NAME = "hello";
    
        public static void main(String[] args) throws Exception {
            // 连接工厂
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("192.168.101.128");
            factory.setPort(5672);
            factory.setUsername("admin");
            factory.setPassword("Gen123");
            factory.setVirtualHost("/");
    
            Connection connection = factory.newConnection();
            Channel channel = connection.createChannel();
    
            // 声明队列
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            // 回调
            DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
                System.out.println("Recv:" + message);
            };
            // 自动确认消息
            channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {
            });
        }
    }
    

2.工作队列

RabbitMQ五大常用工作模式,RabbitMQ,rabbitmq

  • 工作队列

    • 消息生产能力大于消费能力,增加多个消费节点
    • 和简单队列类似,增加多个消费节点,处于竞争关系
    • 默认策略:round robin轮训
  • 生产者

    public class Send {
    
        private static final String QUEUE_NAME = "work_mq";
    
        public static void main(String[] args) throws Exception {
            // 连接工厂
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("192.168.101.128");
            factory.setPort(5672);
            factory.setUsername("admin");
            factory.setPassword("Gen123");
            factory.setVirtualHost("/");
    
            try (Connection connection = factory.newConnection();
                 Channel channel = connection.createChannel()) {
                // 声明队列
                channel.queueDeclare(QUEUE_NAME, false, false, false, null);
                // 批量发送10个消息
                for (int i = 0; i < 10; i++) {
                    String message = "这是一条消息!!!" + i;
                    // 发送消息
                    channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));
                    System.out.println("Send:" + message);
    
                }
            }
        }
    }
    
  • 消费者1

    public class Recv1 {
        private static final String QUEUE_NAME = "work_mq";
    
        public static void main(String[] args) throws Exception {
            // 连接工厂
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("192.168.101.128");
            factory.setPort(5672);
            factory.setUsername("admin");
            factory.setPassword("Gen123");
            factory.setVirtualHost("/");
    
            Connection connection = factory.newConnection();
            Channel channel = connection.createChannel();
    
            // 声明队列
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            // 回调
            DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                // 模拟消费者缓慢
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
                System.out.println("Recv1:" + message);
                // 手工确认消息
                channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
            };
            // 关闭自动确认消息
            channel.basicConsume(QUEUE_NAME, false, deliverCallback, consumerTag -> {
            });
        }
    }
    
  • 消费者2

    public class Recv2 {
        private static final String QUEUE_NAME = "work_mq";
    
        public static void main(String[] args) throws Exception {
            // 连接工厂
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("192.168.101.128");
            factory.setPort(5672);
            factory.setUsername("admin");
            factory.setPassword("Gen123");
            factory.setVirtualHost("/");
    
            Connection connection = factory.newConnection();
            Channel channel = connection.createChannel();
    
            // 声明队列
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            // 回调
            DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                // 模拟消费者缓慢
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
                System.out.println("Recv2:" + message);
                // 手工确认消息
                channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
            };
            // 关闭自动确认消息
            channel.basicConsume(QUEUE_NAME, false, deliverCallback, consumerTag -> {
            });
        }
    }
    
  • 轮训策略验证

    • 先启动两个消费者,再启动生产者
    • 缺点:存在部分节点消费过快,部分节点消费慢,导致不能合理处理消息
  • 公平策略验证

    • 修改消费者策略
    • 解决消费者能力消费不足的问题,降低消费时间问题

RabbitMQ五大常用工作模式,RabbitMQ,rabbitmq

3.RabbitMQ的Exchange交换机

  • 生产者将消息发送到Exchange,交换机将消息路由到一个或者多个队列中,交换机有多个类型,队列和交换机是多对多的关系
  • 交换机只负责转发消息,不具备存储消息的能力,如果没有队列和交换机绑定或者没有符合的路由规则,则消息会被丢失
  • RabbitMQ有四种交换机类型,分别是Direct exchange、Fanout exchange、Topic exchange、Headers exchange,最后一种基本不用

RabbitMQ五大常用工作模式,RabbitMQ,rabbitmq

  • 交换机类型
    • Direct exchange定向
      • 将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配
      • 处理路由键
    • Fanout exchange广播
      • 只需要简单的将队列绑定到交换机上,一个发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息
      • Fanout交换机转发消息是最快的,用于发布订阅广播形式
      • 不处理路由键
    • Topic exchange通配符
      • 主题交换机是一种发布/订阅的模式,结合了直连交换机与扇形交换机的特点
      • 将路由键和某模式进行匹配,此时队列需要绑定在一个模式上
      • 符号"#“匹配一个或多个词,符号”*"匹配不多不少一个词
    • Headers exchange(很少用)
      • 根据发送的消息内容中的headers属性进行匹配,在绑定Queue与Exchange时指定一组键值对
      • 当消息发送到RabbitMQ时会取到该消息的headers与Exchange绑定时指定的键值对进行匹配
      • 如果完全匹配则消息会路由到该队列,否则不会路由到该队列
      • 不处理路由键

4.发布订阅模型

RabbitMQ五大常用工作模式,RabbitMQ,rabbitmq

  • 什么是RabbitMQ的发布订阅模式

    • 发布订阅模型中,消息生产者不再是直接面对队列,而是直面交换机,都需要经过交换机来进行消息的发送,所有发往同一个fanout交换机的消息都会被所有监听这个交换机的消费者接收
    • 发布订阅模型引入fanout交换机
  • 发布订阅模型应用场景

    • 微信公众号
    • 新浪微博关注
  • RabbitMQ发布订阅模型

    • 通过把消息发送给交换机,交换机转发给对应绑定的队列
    • 交换机绑定的队列是排他独占队列,自动删除
  • 发送端

    public class Send {
    
        private static final String EXCHANGE_NAME = "fan_mq";
    
        public static void main(String[] args) throws Exception {
            // 连接工厂
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("192.168.101.128");
            factory.setPort(5672);
            factory.setUsername("admin");
            factory.setPassword("Gen123");
            factory.setVirtualHost("/");
    
            try (Connection connection = factory.newConnection();
                 Channel channel = connection.createChannel()) {
                // 绑定交换机,广播类型
                channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
                String message = "广播发送消息:这是一条消息!!!";
                // 发送消息
                channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes(StandardCharsets.UTF_8));
                System.out.println("Send:" + message);
            }
        }
    }
    
  • 消费端(两个节点)

    public class Recv1 {
        private static final String EXCHANGE_NAME = "fan_mq";
    
        public static void main(String[] args) throws Exception {
            // 连接工厂
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("192.168.101.128");
            factory.setPort(5672);
            factory.setUsername("admin");
            factory.setPassword("Gen123");
            factory.setVirtualHost("/");
    
            Connection connection = factory.newConnection();
            Channel channel = connection.createChannel();
    
            // 绑定交换机,广播类型
            channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
            // 获取队列(排它队列)
            String queueName = channel.queueDeclare().getQueue();
            // 绑定队列和交换机
            channel.queueBind(queueName, EXCHANGE_NAME, "");
            // 回调
            DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
                System.out.println("Recv1:" + message);
            };
            // 自动确认消息
            channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {
            });
        }
    }
    

5.路由模式

RabbitMQ五大常用工作模式,RabbitMQ,rabbitmq

  • 什么是RabbitMQ的路由模式

    • 交换机类型是direct

    • 队列和交换机绑定,需要指定一个路由键(也叫binding key)

    • 消息生产者发送消息给交换机,需要指定路由键

    • 交换机根据消息的路由键,转发给对应的队列

  • 消息生产者

    public class Send {
    
        private static final String EXCHANGE_NAME = "direct_mq";
    
        public static void main(String[] args) throws Exception {
            // 连接工厂
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("192.168.101.128");
            factory.setPort(5672);
            factory.setUsername("admin");
            factory.setPassword("Gen123");
            factory.setVirtualHost("/");
    
            try (Connection connection = factory.newConnection();
                 Channel channel = connection.createChannel()) {
                // 绑定交换机,直连类型
                channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
                String error = "我是错误日志";
                String info = "我是info日志";
                String warning = "我是warning日志";
                // 发送消息
                channel.basicPublish(EXCHANGE_NAME, "error", null, error.getBytes(StandardCharsets.UTF_8));
                channel.basicPublish(EXCHANGE_NAME, "info", null, info.getBytes(StandardCharsets.UTF_8));
                channel.basicPublish(EXCHANGE_NAME, "warning", null, warning.getBytes(StandardCharsets.UTF_8));
                System.out.println("Send:消息发送成功!");
            }
        }
    }
    
  • 消费者一(只接收错误消息)

    public class Recv1 {
        private static final String EXCHANGE_NAME = "direct_mq";
    
        public static void main(String[] args) throws Exception {
            // 连接工厂
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("192.168.101.128");
            factory.setPort(5672);
            factory.setUsername("admin");
            factory.setPassword("Gen123");
            factory.setVirtualHost("/");
    
            Connection connection = factory.newConnection();
            Channel channel = connection.createChannel();
    
            // 绑定交换机,直连类型
            channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
            // 获取队列
            String queueName = channel.queueDeclare().getQueue();
            // 绑定队列和交换机
            channel.queueBind(queueName, EXCHANGE_NAME, "error");
            // 回调
            DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
                System.out.println("Recv1:" + message);
            };
            // 自动确认消息
            channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {
            });
        }
    }
    
  • 消费者二(接收全部消息)

    public class Recv2 {
        private static final String EXCHANGE_NAME = "direct_mq";
    
        public static void main(String[] args) throws Exception {
            // 连接工厂
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("192.168.101.128");
            factory.setPort(5672);
            factory.setUsername("admin");
            factory.setPassword("Gen123");
            factory.setVirtualHost("/");
    
            Connection connection = factory.newConnection();
            Channel channel = connection.createChannel();
    
            // 绑定交换机,直连类型
            channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
            // 获取队列
            String queueName = channel.queueDeclare().getQueue();
            // 绑定队列和交换机
            channel.queueBind(queueName, EXCHANGE_NAME, "error");
            channel.queueBind(queueName, EXCHANGE_NAME, "info");
            channel.queueBind(queueName, EXCHANGE_NAME, "warning");
            // 回调
            DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
                System.out.println("Recv2:" + message);
            };
            // 自动确认消息
            channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {
            });
        }
    }
    

6.主题通配符模式

RabbitMQ五大常用工作模式,RabbitMQ,rabbitmq

  • 什么是RabbitMQ的主题模式

    • 交换机是topic,可以实现发布订阅模式fanout和路由模式direct的功能,更加灵活,支持通配符匹配
    • 交换机通过通配符进行转发到对应的队列,*代表一个词,#代表1个或多个词,一般用#作为通配符居多,词与词之间使用.点进行分割
    • 注意:交换机和队列绑定时用的binding使用通配符的路由键;生产者发送消息时需要使用具体的路由键
  • 生产者

    public class Send {
    
        private static final String EXCHANGE_NAME = "topic_mq";
    
        public static void main(String[] args) throws Exception {
            // 连接工厂
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("192.168.101.128");
            factory.setPort(5672);
            factory.setUsername("admin");
            factory.setPassword("Gen123");
            factory.setVirtualHost("/");
    
            try (Connection connection = factory.newConnection();
                 Channel channel = connection.createChannel()) {
                // 绑定交换机,主题类型
                channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
                String error = "我是错误日志";
                String info = "我是info日志";
                String warning = "我是warning日志";
                // 发送消息
                channel.basicPublish(EXCHANGE_NAME, "error", null, error.getBytes(StandardCharsets.UTF_8));
                channel.basicPublish(EXCHANGE_NAME, "info", null, info.getBytes(StandardCharsets.UTF_8));
                channel.basicPublish(EXCHANGE_NAME, "warning", null, warning.getBytes(StandardCharsets.UTF_8));
                System.out.println("Send:消息发送成功!");
            }
        }
    }
    
  • 消费者一(只接收错误消息)

    public class Recv1 {
        private static final String EXCHANGE_NAME = "topic_mq";
    
        public static void main(String[] args) throws Exception {
            // 连接工厂
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("192.168.101.128");
            factory.setPort(5672);
            factory.setUsername("admin");
            factory.setPassword("Gen123");
            factory.setVirtualHost("/");
    
            Connection connection = factory.newConnection();
            Channel channel = connection.createChannel();
    
            // 绑定交换机,主题类型
            channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
            // 获取队列
            String queueName = channel.queueDeclare().getQueue();
            // 绑定队列和交换机
            channel.queueBind(queueName, EXCHANGE_NAME, "error");
            // 回调
            DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
                System.out.println("Recv1:" + message);
            };
            // 自动确认消息
            channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {
            });
        }
    }
    
  • 消费者二(接收全部消息)

    public class Recv2 {
        private static final String EXCHANGE_NAME = "topic_mq";
    
        public static void main(String[] args) throws Exception {
            // 连接工厂
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("192.168.101.128");
            factory.setPort(5672);
            factory.setUsername("admin");
            factory.setPassword("Gen123");
            factory.setVirtualHost("/");
    
            Connection connection = factory.newConnection();
            Channel channel = connection.createChannel();
    
            // 绑定交换机,主题类型
            channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
            // 获取队列
            String queueName = channel.queueDeclare().getQueue();
            // 绑定队列和交换机
            channel.queueBind(queueName, EXCHANGE_NAME, "#");
            // 回调
            DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
                System.out.println("Recv2:" + message);
            };
            // 自动确认消息
            channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {
            });
        }
    }
    

7.工作模式总结

  • 简单模式

    • 一个生产者一个消费者,不用指定交换机,使用默认交换机
  • 工作队列模式

    • 一个生产者多个消费者,可以有轮训和公平策略,不用指定交换机,使用默认交换机
  • 发布订阅模式

    • fanout类型交换机,通过交换机和队列绑定,不用指定绑定路由键,生产者发送消息到交换机,fanout交换机直接进行转发,消息不用指定routingkey路由键
  • 路由模式

    • direct类型交换机,通过交换机和队列绑定,指定绑定的路由键,生产者发送消息到交换机,交换机根据消息的路由key进行转发到对应的队列,消息要指定routingkey路由键
  • 通配符模式文章来源地址https://www.toymoban.com/news/detail-825773.html

    • topic交换机,通过交换机和队列绑定,指定绑定的通配符路由键,生产者发送消息到交换机,交换机根据消息的路由键进行转发到对应的队列,消息要指定routingkey路由键

到了这里,关于RabbitMQ五大常用工作模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • RabbitMQ工作模式-主题模式

    主题模式 官方文档参考:https://www.rabbitmq.com/tutorials/tutorial-five-python.html 使用topic类型的交换器,队列绑定到交换器、bingingKey时使用通配符,交换器将消息路由转发到具体队列时,会根据消息routingKey模糊匹配,比较灵活。 在Direct类型的交换器做到了根据日志级别的不同,将消

    2024年02月10日
    浏览(35)
  • RabbitMQ的工作模式

    RabbitMQ 的工作模式 一 .simple 模式(即最简单的收发模式) 二 .work 工作模式 ( 资源的竞争 ) publish_subscribe 发布订阅 (../../../../../0 马士兵 / 新建文件夹 /BAT 面试突击资料 (1)/ 整理 /BAT 面试突击资料 /15- 消息中间件 MQ 面试题( 2020 最新 版) .assets/publish_subscribe 发布订阅 ( 共享资

    2024年02月06日
    浏览(73)
  • RabbitMQ 工作模式介绍

    RabbitMQ 是一个消息代理:它接受并转发消息。您可以将其视为邮局:当您将要邮寄的邮件放入邮箱时,您可以确定信使最终会将邮件交付给您的收件人。在这个类比中,RabbitMQ是一个邮政信箱,一个邮局和一个信件载体。 RabbitMQ 和邮局之间的主要区别在于它不处理纸张,而是

    2024年02月06日
    浏览(43)
  • RabbitMQ:工作队列模式

    📃个人主页:不断前进的皮卡丘 🌞博客描述:梦想也许遥不可及,但重要的是追梦的过程,用博客记录自己的成长,记录自己一步一步向上攀登的印记 🔥个人专栏:消息中间件 工作队列(又名: 任务队列 )背后的主要思想是避免立即执行资源密集型任务并等待其完成。相反

    2024年01月23日
    浏览(41)
  • RabbitMQ的6种工作模式

    官方文档: http://www.rabbitmq.com/ https://www.rabbitmq.com/getstarted.html RabbitMQ 常见的 6 种工作模式: 1)、消息产生后将消息放入队列。 2)、消息的消费者监听消息队列,如果队列中有消息,就消费掉,消息被拿走后,自动从队列中删除。 3)、存在的问题:消息可能没有被消费者正确处

    2024年02月14日
    浏览(41)
  • 消息队列之RabbitMQ工作模式

    提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 消息队列之RabbitMQ工作模式 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 提示:这里可以添加本文要记录的大概内容: 在这篇博客中,我将深入探讨 RabbitMQ 的工作模式,带你

    2024年01月18日
    浏览(56)
  • RabbitMQ消息队列的工作模式

    官方文档地址:https://www.rabbitmq.com/getstarted.html 工作模式其实就是消息队列分发消息的路由方式。 RabbitMQ常用的几种工作模式: 简单模式 WorkQueues工作队列模式 PubSub生产者/PubSub消费者模式 Routing路由模式 Topics通配符模式 发布/订阅模式(Publish/Subscribe):该模式用于一对多的

    2024年02月15日
    浏览(46)
  • RabbitMQ的5种模式——再探RabbitMQ的模式,简单、工作,发布订阅(广播),路由、主题 & 页面分析

    RabbitMQ作为一款常用的消息中间件,在微服务项目中得到大量应用,其本身是微服务中的重点和难点,有不少概念我自己的也是一知半解,本系列博客尝试结合实际应用场景阐述RabbitMQ的应用,分析其为什么使用,并给出怎么用的案例。 本篇博客结合场景来阐述RabbitMQ的几种模

    2024年02月07日
    浏览(45)
  • 消息队列——rabbitmq的不同工作模式

    目录 Work queues 工作队列模式  Pub/Sub 订阅模式 Routing路由模式 Topics通配符模式   工作模式总结 C1和C2属于竞争关系,一个消息只有一个消费者可以取到。  代码部分只需要用两个消费者进程监听同一个队里即可。 两个消费者呈现竞争关系。 用一个生产者推送10条消息 两个监

    2024年02月16日
    浏览(45)
  • RabbitMQ Exchange类型和工作模式介绍

    RabbitMQ常用的交换器类型有: fanout、 direct、 topic、 headers四种。 会把所有发送到该交换器的消息路由到所有与该交换器绑定的队列中 如图: direct类型的交换器路由规则很简单,它会把消息路由到那些BindingKey和RoutingKey完全匹配的 队列中 ,如下图: topic类型的交换器在direc

    2024年02月11日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包