国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

RabbitMQ系列(17)--延遲隊列的簡介與實現(xiàn)

這篇具有很好參考價值的文章主要介紹了RabbitMQ系列(17)--延遲隊列的簡介與實現(xiàn)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

1、延遲隊列的概念

延遲隊列內(nèi)部是有序的,重要的特性體現(xiàn)在它的延遲屬性上,延遲隊列中的元素希望在指定時間到了之后或之前取出處理,簡單的說延遲隊列就是用來存放需要在指定時間被處理的元素的隊列。

2、延遲隊列的應用場景

(1)訂單指定時間內(nèi)未支付則自動取消

(2)用戶發(fā)起退款,指定時間內(nèi)未處理則通知相關運營人員

3、定時任務和延遲隊列的取舍

以上場景都有一個特點,那就是都需要在某個事件發(fā)生前或發(fā)生后執(zhí)行一項任務,如生成訂單后,在十分鐘后檢查訂單狀態(tài),未支付的訂單將關閉,這種場景也可以用定時任務來處理,但數(shù)據(jù)量比價少的話確實可以用定時任務來處理,但在活動期間,訂單的數(shù)據(jù)量可能會變得很龐大,對于龐大的數(shù)據(jù),定時任務很難在1秒內(nèi)檢查完訂單,從而不能及時的關閉未支付的訂單,而且用定時任務來檢查訂單會給數(shù)據(jù)庫帶來很大的壓力,所以在數(shù)據(jù)量大的情況下,定時任務無法滿足業(yè)務需求且性能低下

4、延遲隊列架構圖?(后面我們就根據(jù)這個架構圖進行代碼的設計與實現(xiàn))

mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq

??

5、延遲隊列的實現(xiàn)

(1)新建一個名為config的包,用于裝實現(xiàn)特定配置的代碼mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq

效果圖:

mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq

(2)在config包里新建一個名為TtlQueueConfig的類用于編寫配置隊列延遲的代碼

mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq

代碼如下:

package com.ken.springbootrqbbitmq.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * 用于配置TTL隊列的延遲時間
 */
@Configuration
public class TtlQueueConfig {

    //普通交換機的名稱
    public static final String NORMAL_EXCHANGE = "normal_exchange";
    //死信交換機的名稱
    public static final String DEAD_EXCHANGE = "dead_exchange";

    //普通隊列的名稱
    public static final String NORMAL_QUEUE01 = "normal_queue01";
    public static final String NORMAL_QUEUE02 = "normal_queue02";

    //死信隊列的名稱
    public static final String DEAD_QUEUE = "dead_queue";

    //聲明普通交換機
    @Bean("normalExchange")
    public DirectExchange normalExchange() {
        return new DirectExchange(NORMAL_EXCHANGE);
    }

    //聲明交換機交換機
    @Bean("deadExchange")
    public DirectExchange deadExchange() {
        return new DirectExchange(DEAD_EXCHANGE);
    }

    //聲明普通隊列,TTL為10S
    @Bean("normalQueue01")
    public Queue normalQueue01() {
        Map<String, Object> arguments = new HashMap<>();
        //設置死信交換機
        arguments.put("x-dead-letter-exchange",DEAD_EXCHANGE);
        //設置死信RoutignKey
        arguments.put("x-dead-letter-routing-key","dead");
        //設置TTL
        arguments.put("x-message-ttl",10000);
        return QueueBuilder.durable(NORMAL_QUEUE01).withArguments(arguments).build();
    }

    //聲明普通隊列,TTL為40S
    @Bean("normalQueue02")
    public Queue normalQueue02() {
        Map<String, Object> arguments = new HashMap<>();
        //設置死信交換機
        arguments.put("x-dead-letter-exchange",DEAD_EXCHANGE);
        //設置死信RoutignKey
        arguments.put("x-dead-letter-routing-key","dead");
        //設置TTL
        arguments.put("x-message-ttl",40000);
        return QueueBuilder.durable(NORMAL_QUEUE02).withArguments(arguments).build();
    }

    //聲明死信隊列
    @Bean("deadQueue")
    public Queue deadQueue() {
        return QueueBuilder.durable(DEAD_QUEUE).build();
    }

    //綁定隊列1和普通交換機
    @Bean
    public Binding queue01BindNormalExchange(@Qualifier("normalQueue01") Queue normalQueue01,
                                             @Qualifier("normalExchange") DirectExchange normalExchange) {
        return BindingBuilder.bind(normalQueue01).to(normalExchange).with("normal01");
    }

    //綁定隊列2和普通交換機
    @Bean
    public Binding queue02BindNormalExchange(@Qualifier("normalQueue02") Queue normalQueue02,
                                             @Qualifier("normalExchange") DirectExchange normalExchange) {
        return BindingBuilder.bind(normalQueue02).to(normalExchange).with("normal02");
    }

    //綁定隊列2和普通交換機
    @Bean
    public Binding deadQueueBindDeadExchange(@Qualifier("deadQueue") Queue deadQueue,
                                             @Qualifier("deadExchange") DirectExchange deadExchange) {
        return BindingBuilder.bind(deadQueue).to(deadExchange).with("dead");
    }

}

(3)新建一個名為controller的包,用于裝控制層的代碼mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq

效果圖:

mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq

(4)新建一個名為SendMsgController的類用于充當生產(chǎn)者用于發(fā)送消息

mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq

?代碼如下:

package com.ken.springbootrqbbitmq.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

/**
 * 發(fā)送延遲消息
 */
@Slf4j
@RequestMapping("ttl")
@RestController
public class SendMsgController {

    @Autowired(required = false)
    private RabbitTemplate rabbitTemplate;

    @GetMapping("/sendMsg/{message}")
    public void sendMsg(@PathVariable String message) {
        log.info("當前時間:{},發(fā)送一條消息給兩個TTL隊列:{}",new Date().toString(),message);
        rabbitTemplate.convertAndSend("normal_exchange","normal01","消息來著ttl為10s的隊列:" + message);
        rabbitTemplate.convertAndSend("normal_exchange","normal02","消息來著ttl為40s的隊列:" + message);
    }

}

(5)新建一個名為consumer的包,用于裝消費者的代碼

mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq

效果圖:

mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq

(6)新建一個名為DeadQueueConsumer的類用于消費死信隊列里的消息

mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq

代碼如下:

package com.ken.springbootrqbbitmq.consumer;

import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * 死信隊列消費者
 */
@Slf4j
@Component
public class DeadQueueConsumer {

    //接收消息
    @RabbitListener(queues = "dead_queue")
    public void receiveMsg(Message message, Channel channel) throws Exception {
        String msg = new String(message.getBody());
        log.info("當前時間:{},收到死信隊列的消息:{}",new Date().toString(),msg);
    }

}

(7)進入項目的啟動類啟動項目

mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq

(8)啟動完畢后在瀏覽器地址欄輸入http://localhost:8080/ttl/sendMsg/參數(shù)往隊列發(fā)送消息

mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq?

?(9)查看控制臺的輸出,發(fā)現(xiàn)分別在10s和40s后進行輸出,這證明我們的延遲隊列成功運行

mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq?

6、延遲隊列的優(yōu)化

雖然上述能實現(xiàn)延遲隊列,但上述的實現(xiàn)過程是一個隊列只能延遲固定的已經(jīng)設置好的時間,若想增加一個新的時間需要,用上述的實現(xiàn)方法就只能新增一個隊列,這樣很麻煩,所以我們需要優(yōu)化延遲隊列

(1)延遲隊列優(yōu)化架構圖?(后面我們就根據(jù)這個架構圖對延遲隊列進行優(yōu)化)

mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq

(2)修改config包里TtlQueueConfig類的代碼,多加一些關于NormalQueue03隊列的配置

代碼如下:

package com.ken.springbootrqbbitmq.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * 用于配置TTL隊列的延遲時間
 */
@Configuration
public class TtlQueueConfig {

    //普通交換機的名稱
    public static final String NORMAL_EXCHANGE = "normal_exchange";
    //死信交換機的名稱
    public static final String DEAD_EXCHANGE = "dead_exchange";

    //普通隊列的名稱
    public static final String NORMAL_QUEUE01 = "normal_queue01";
    public static final String NORMAL_QUEUE02 = "normal_queue02";
    //自定義延遲時間隊列的名稱
    public static final String NORMAL_QUEUE03 = "normal_queue03";

    //死信隊列的名稱
    public static final String DEAD_QUEUE = "dead_queue";

    //聲明普通交換機
    @Bean("normalExchange")
    public DirectExchange normalExchange() {
        return new DirectExchange(NORMAL_EXCHANGE);
    }

    //聲明交換機交換機
    @Bean("deadExchange")
    public DirectExchange deadExchange() {
        return new DirectExchange(DEAD_EXCHANGE);
    }

    //聲明普通隊列,TTL為10S
    @Bean("normalQueue01")
    public Queue normalQueue01() {
        Map<String, Object> arguments = new HashMap<>(3);
        //設置死信交換機
        arguments.put("x-dead-letter-exchange",DEAD_EXCHANGE);
        //設置死信RoutignKey
        arguments.put("x-dead-letter-routing-key","dead");
        //設置TTL
        arguments.put("x-message-ttl",10000);
        return QueueBuilder.durable(NORMAL_QUEUE01).withArguments(arguments).build();
    }

    //聲明普通隊列,TTL為40S
    @Bean("normalQueue02")
    public Queue normalQueue02() {
        Map<String, Object> arguments = new HashMap<>(3);
        //設置死信交換機
        arguments.put("x-dead-letter-exchange",DEAD_EXCHANGE);
        //設置死信RoutignKey
        arguments.put("x-dead-letter-routing-key","dead");
        //設置TTL
        arguments.put("x-message-ttl",40000);
        return QueueBuilder.durable(NORMAL_QUEUE02).withArguments(arguments).build();
    }

    //聲明普通隊列,TTL為40S
    @Bean("normalQueue03")
    public Queue normalQueue03() {
        Map<String, Object> arguments = new HashMap<>(3);
        //設置死信交換機
        arguments.put("x-dead-letter-exchange",DEAD_EXCHANGE);
        //設置死信RoutignKey
        arguments.put("x-dead-letter-routing-key","dead");
        //設置TTL
        return QueueBuilder.durable(NORMAL_QUEUE03).withArguments(arguments).build();
    }

    //聲明死信隊列
    @Bean("deadQueue")
    public Queue deadQueue() {
        return QueueBuilder.durable(DEAD_QUEUE).build();
    }

    //綁定隊列1和普通交換機
    @Bean
    public Binding queue01BindNormalExchange(@Qualifier("normalQueue01") Queue normalQueue01,
                                             @Qualifier("normalExchange") DirectExchange normalExchange) {
        return BindingBuilder.bind(normalQueue01).to(normalExchange).with("normal01");
    }

    //綁定隊列2和普通交換機
    @Bean
    public Binding queue02BindNormalExchange(@Qualifier("normalQueue02") Queue normalQueue02,
                                             @Qualifier("normalExchange") DirectExchange normalExchange) {
        return BindingBuilder.bind(normalQueue02).to(normalExchange).with("normal02");
    }

    //綁定隊列3和普通交換機
    @Bean
    public Binding queue03BindNormalExchange(@Qualifier("normalQueue03") Queue normalQueue03,
                                             @Qualifier("normalExchange") DirectExchange normalExchange) {
        return BindingBuilder.bind(normalQueue03).to(normalExchange).with("normal03");
    }

    //綁定死信隊列和死信交換機
    @Bean
    public Binding deadQueueBindDeadExchange(@Qualifier("deadQueue") Queue deadQueue,
                                             @Qualifier("deadExchange") DirectExchange deadExchange) {
        return BindingBuilder.bind(deadQueue).to(deadExchange).with("dead");
    }

}

(3)修改controller包里SendMsgController類的代碼,多加一個調(diào)用自定義延遲時間NormalQueue03隊列的接口

代碼如下:

package com.ken.springbootrqbbitmq.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

/**
 * 發(fā)送延遲消息
 */
@Slf4j
@RequestMapping("ttl")
@RestController
public class SendMsgController {

    @Autowired(required = false)
    private RabbitTemplate rabbitTemplate;

    @GetMapping("/sendMsg/{message}")
    public void sendMsg(@PathVariable String message) {
        log.info("當前時間:{},發(fā)送一條消息給兩個TTL隊列:{}",new Date().toString(),message);
        rabbitTemplate.convertAndSend("normal_exchange","normal01","消息來著ttl為10s的隊列:" + message);
        rabbitTemplate.convertAndSend("normal_exchange","normal02","消息來著ttl為40s的隊列:" + message);
    }

    @GetMapping("/sendExpirationMsg/{message}/{ttlTime}")
    public void sendMsg(@PathVariable String message,@PathVariable String ttlTime) {
        log.info("當前時間:{},發(fā)送一條時長{}毫秒的TTL消息給normal03隊列:{}", new Date(),ttlTime,message);
        rabbitTemplate.convertAndSend("normal_exchange","normal03",message,msg -> {
            //發(fā)送消息的時候延遲時長
            msg.getMessageProperties().setExpiration(ttlTime);
            return msg;
        });
    }

}

?(4)進入項目的啟動類重新啟動項目

mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq

(5)啟動完畢后分別在瀏覽器地址欄輸http://localhost:8080/ttl/sendExpirationMsg/第一個參數(shù)/20000和http://localhost:8080/ttl/sendExpirationMsg/第二個參數(shù)/2000隊列發(fā)送消息

例:

mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq?

mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq

?(6)查看控制臺的輸出,發(fā)現(xiàn)第一條消息在20s后進行了輸出,這證明我們優(yōu)化后的延遲隊列成功運行?,但當我們發(fā)送多條消息時,消息可能不會按時"死亡"從而不能按時把消息發(fā)送到死信隊列,如圖里的第二條消息,在第一條消息被消費后緊跟著被消費,而不是隔2秒后被消費,這是因為RabbitMQ只會檢查第一條消息是否過期,過期則會被扔進死信隊列,如果第一條消息延遲時間很長,第二條消息延遲時間很短,第二條消息也并不會被優(yōu)先消費,而是等到第一條消息被消費后第二條消息再被消費,這時需要我們用另一種方法去實現(xiàn)延遲隊列(另一種方法放在下一篇文章介紹)

mq實現(xiàn)延遲隊列,rabbitmq,rabbitmq,java-rabbitmq文章來源地址http://www.zghlxwxcb.cn/news/detail-726587.html

到了這里,關于RabbitMQ系列(17)--延遲隊列的簡介與實現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • RabbitMQ實現(xiàn)延遲消息的方式-死信隊列、延遲隊列和惰性隊列

    當一條消息因為一些原因無法被成功消費,那么這這條消息就叫做死信,如果包含死信的隊列配置了dead-letter-exchange屬性指定了一個交換機,隊列中的死信都會投遞到這個交換機內(nèi),這個交換機就叫死信交換機,死信交換機再綁定一個隊列,死信最終會進入到這個存放死信的

    2024年02月19日
    瀏覽(94)
  • RabbitMQ之TTL+死信隊列實現(xiàn)延遲隊列

    RabbitMQ是一個流行的消息隊列系統(tǒng),它提供了許多有用的功能,其中之一是TTL(Time To Live)和死信隊列。這些功能可以用來實現(xiàn)延遲隊列,讓我們來看看如何使用它們。 首先,什么是TTL?TTL是消息的存活時間,它可以設置為一個特定的時間段。如果消息在這個時間段內(nèi)沒有被

    2024年02月13日
    瀏覽(18)
  • Springboot集成rabbitmq——實現(xiàn)延遲隊列

    Springboot集成rabbitmq——實現(xiàn)延遲隊列

    目錄 1.rabbitmq簡介 2.延遲隊列 3.Springboot集成rabbitmq 4.以死信隊列形式實現(xiàn) 5.以插件形式實現(xiàn) ?MQ(message queue),從字面意思上看,本質是個隊列,遵從先入先出的規(guī)則,只不過隊列中存放的內(nèi)容是 message 而已,是一種跨進程的通信機制,用于上下游傳遞消息。RabbitMq是開發(fā)中常用

    2024年02月05日
    瀏覽(26)
  • Rabbitmq入門與應用(五)-延遲隊列的設計與實現(xiàn)

    Rabbitmq入門與應用(五)-延遲隊列的設計與實現(xiàn)

    在開發(fā)過程中涉及到延遲隊列的應用,例如訂單生成后有30分鐘的付款時間,注冊是有60秒的郵件或者短信的發(fā)送讀取時間等。 常規(guī)使用rabbitmq設計延遲隊列有兩種方式 使用創(chuàng)建一個延遲隊列阻塞消息 使用延遲隊列插件 Dead Letter Exchanges — RabbitMQ 配置 To set the DLX for a queue, s

    2024年02月21日
    瀏覽(26)
  • rabbitMq實現(xiàn)延遲隊列,阿里最愛考的前端面試題

    rabbitMq實現(xiàn)延遲隊列,阿里最愛考的前端面試題

    @Qualifier(“deadLetterExchange”) DirectExchange exchange) { return BindingBuilder.bind(queue).to(exchange).with(DEAD_LETTER_QUEUEA_ROUTING_KEY); } // 聲明死信隊列B綁定關系 @Bean public Binding deadLetterBindingB(@Qualifier(“deadLetterQueueB”) Queue queue, @Qualifier(“deadLetterExchange”) DirectExchange exchange) { return BindingBuilder.

    2024年04月14日
    瀏覽(19)
  • SpringCloudStream整合RabbitMQ用ttl+死信實現(xiàn)延遲隊列的實踐

    這篇是關于我使用Spring Cloud Steam操作RabbitMQ采用ttl+死信隊列的方式實現(xiàn)的延遲隊列。 在公司項目中遇到了需要延遲隊列的需求,為了以后可維護性和擴展性要求必須要用Springcloud Stream組件來操作mq,而且公司的rabbit也不允許安裝延遲插件,只能用最原始的ttl+死信來實現(xiàn),在搭

    2024年02月12日
    瀏覽(26)
  • 消息隊列中間件,RabbitMQ的使用,死信隊列,延遲隊列,利用枚舉實現(xiàn)隊列,交換機,RountKey的聲明

    消息隊列中間件,RabbitMQ的使用,死信隊列,延遲隊列,利用枚舉實現(xiàn)隊列,交換機,RountKey的聲明

    目錄 0.交換機種類和區(qū)別 1.聲明隊列和交換機以及RountKey 2.初始化循環(huán)綁定 3.聲明交換機 4.監(jiān)聽隊列 4.1 監(jiān)聽普通隊列 4.2監(jiān)聽死信隊列 ?5.削峰填谷的實現(xiàn) Direct Exchange(直連交換機) : 直連交換機將消息發(fā)送到與消息的路由鍵完全匹配的隊列。它是最簡單的交換機類型之一。

    2024年04月23日
    瀏覽(586)
  • 【RabbitMQ】RabbitMQ高級:死信隊列和延遲隊列

    【RabbitMQ】RabbitMQ高級:死信隊列和延遲隊列

    在電商平臺下單,訂單創(chuàng)建成功,等待支付,一般會給30分鐘的時間,開始倒計時。如果在這段時間內(nèi)用戶沒有支付,則默認訂單取消。 該如何實現(xiàn)? 定期輪詢(數(shù)據(jù)庫等) 用戶下單成功,將訂單信息放入數(shù)據(jù)庫,同時將支付狀態(tài)放入數(shù)據(jù)庫,用戶付款更改數(shù)據(jù)庫狀態(tài)。定

    2024年01月17日
    瀏覽(18)
  • MQ-消息隊列-RabbitMQ

    MQ-消息隊列-RabbitMQ

    MQ(Message Queue) 消息隊列 ,是基礎數(shù)據(jù)結構中“ 先進先出 ”的一種 數(shù)據(jù)結構 。指把要傳輸?shù)臄?shù)據(jù)(消息)放在隊列中,用隊列機制來實現(xiàn)消息傳遞——生產(chǎn)者產(chǎn)生消息并把消息放入隊列,然后由消費者去處理。消費者可以到指定隊列拉取消息,或者訂閱相應的隊列,由

    2024年02月09日
    瀏覽(25)
  • RabbitMQ --- 惰性隊列、MQ集群

    RabbitMQ --- 惰性隊列、MQ集群

    當生產(chǎn)者發(fā)送消息的速度超過了消費者處理消息的速度,就會導致隊列中的消息堆積,直到隊列存儲消息達到上限。之后發(fā)送的消息就會成為死信,可能會被丟棄,這就是消息堆積問題。 解決消息堆積有三種思路: 增加更多消費者,提高消費速度。也就是我們之前說的work

    2024年02月03日
    瀏覽(39)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包