RabbitMQ入门篇【图文并茂,超级详细】

这篇具有很好参考价值的文章主要介绍了RabbitMQ入门篇【图文并茂,超级详细】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🥳🥳Welcome 的Huihui's Code World ! !🥳🥳

接下来看看由辉辉所写的关于RabbitMQ的相关操作吧

目录

🥳🥳Welcome 的Huihui's Code World ! !🥳🥳

前言

1.什么是MQ

2.理解MQ

3.生活案例分析与理解

4.MQ的使用场景

(1)解耦

传统模式

中间件模式

(2)削峰

传统模式

中间件模式

(3)异步

 传统模式

中间件模式

5.常见的MQ

一. RabbitMQ是什么

 二. Docker安装部署RabbitMQ

 1.拉取镜像

2.安装

3.访问

三.springboot连接配置

1.进入rabbitmq管理界面

2.创建用户

3.分配权限给用户

四.代码实现简单队列 

1.创建一个生产者模块

2.创建一个消费者模块

3.代码操作

(1)配置RabbitMQ消息队列

(2)向消息队列发消息

(3)连接rabbitmq测试

(4)RabbitMQ消息队列的消费者

(5)成自定义数据发送

①配置RabbitMQ消息队列

②RabbitMQ消息队列的消费者

五.本篇问题总结

1.端口没开

2.配置文件的层级关系

3.配置文件中的信息核对


前言

        其实在讲解RabbitMQ之前,我们应该先明白为什么要使用RabbitMQ,RabbitMQ能给我们带来什么效益...

       在公司中做项目时,当项目已经迭代了几个版本了,代码量已经很大了,此时我们需要再增加一个业务功能那么这就需要提供新增一个业务接口,但如果这个时候再去更改原来的代码就会很困难,需要修改很多的地方。。。

        其实这个时候我们就可以使用到消息队列去优化项目,这样就算我们后来有新的功能需要添加,也不用跟上面一样修改很多的代码。

1.什么是MQ

Message queue相当于一个中间件,用于生产方通过MQ与消费方之间的交互作用

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

服务之间最常见的通信方式是直接调用彼此来通信,消息从一端发出后立即就可以达到另一端,称为即时消息通讯(同步通信)

也就是两人面对面交流,必须同步进行,除此之外不做任何事情,就像打电话一样的

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

消息从某一端发出后,首先进入一个容器进行临时存储,当达到某种条件后,再由这个容器发送给另一端,称为延迟消息通讯(异步通信)

相当于通过第三方转述对话,可能有消息的延迟,但不需要二人时刻保持联系,消息传给第三方后,两人可以做其他自己想做的事情,当需要获取对方说话的内容时,直接从消息队列里获取即可。就像发微信一样

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

2.理解MQ

  • 消息:就是两台计算机间传送的数据单位;本质上就是一段数据,它能被一个或者多个应用程序所理解,是应用程序之间传递的信息载体。消息可以非常简单,例如只包含文本字符串;也可以更复杂地嵌入对象。
  • 队列:是数据结构中概念。在队列中,数据先进先出,后进后出,犹如排队做核酸。
  • 消息队列:MQ是把消息和队列结合起来,称之为消息队列(Message Queue)。把要传输的数据(消息)与队列进行绑定,用队列先进先出机制来实现消息传递。消息队列由 生产者 和 消费者 两部分构成;生产者主要负责产生消息并把消息放入队列中,再由消费者去处理。消费者可以到指定队列中获取消息,或者订阅相应的队列,最后由MQ服务端进行消息推送。

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

3.生活案例分析与理解

看书案例

小红希望小明多读书,常寻找好书给小明看,之前的方式是这样:小红问小明什么时候有空,把书给小明送去,并亲眼监督小明读完书才走.久而久之,两人都觉得麻烦. 后来的方式改成了:小红对小明说「我放到书架上的书你都要看」,然后小红每次发现不错的书都放到书架上,小明则看到书架上有书就拿下来看.【书架就是一个消息队列,小红是生产者,小明是消费者.】

案例分析

改变方式之后带来的好处

  • 1. 小红想给小明书的时候,不必问小明什么时候有空,亲手把书交给他了,小红只把书放到书架上就行了.这样小红小明的时间都更自由.
  • 2. 小红相信小明的读书自觉和读书能力,不必亲眼观察小明的读书过程,小红只要做一个放书的动作,很节省时间.
  • 3. 当明天有另一个爱读书的小伙伴小强加入,小红仍旧只需要把书放到书架上,小明和小强从书架上取书即可
  • 4. 书架上的书放在那里,小明阅读速度快就早点看完,阅读速度慢就晚点看完,没关系,比起小红把书递给小明并监督小明读完的方式,小明的压力会小一些

消息队列特点

  • 1. 解耦:每个成员不必受其他成员影响,可以更独立自主,只通过一个简单的容器来联系.
  • 2. 提速:小红选只要做一个放书的动作,为自己节省了大量时间.
  • 3. 广播:小红只需要劳动一次,就可以让多个小伙伴有书可读,这大大地节省了她的时间,也让新的小伙伴的加入成本很低.
  • 4. 错峰与流控:小红给书的频率不稳定,如果今明两天连给了五本,之后隔三个月才又给一本,那小明只要在三个月内从书架上陆续取走五本书读完就行了,压力就不那么大了.

也可以用生活中做核酸的例子来理解一下

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

4.MQ的使用场景

上面也已经用生活案例说明的MQ的使用的好处(场景),这里再来罗列以及分析对比一下...

(1)解耦

传统模式

系统间耦合性太强,如图所示,系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦!

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

中间件模式

将消息写入消息队列,需要消息的系统自己从消息队列中订阅,从而系统A不需要做任何修改。

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

(2)削峰

传统模式

并发量大的时候,所有的请求直接怼到数据库,造成数据库连接异常

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

中间件模式

系统A慢慢的按照数据库能处理的并发量,从消息队列中慢慢拉取消息

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

(3)异步

 传统模式

一些非必要的业务逻辑以同步的方式运行,太耗费时间

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

中间件模式

 将消息写入消息队列,非必要的业务逻辑以异步的方式运行,加快响应速度

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

5.常见的MQ

消息队列有很多,这里我们使用的是RabbitMQ,也可以选择使用其他的MQ...

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

那么接下来我就来讲述一下RabbitMQ的相关点

一. RabbitMQ是什么

        RabbitMQ是一种开源的消息队列软件,它实现了高级消息队列协议(AMQP)标准。它可以在分布式系统中作为消息传递的中间层来处理异步通信和解耦。通过将生产者和消费者解耦,RabbitMQ可以提高系统的可靠性、扩展性和可维护性。它还支持多种编程语言和平台,并且具有许多高级功能,例如消息确认、消息持久化、消息路由和负载均衡等。RabbitMQ在企业应用程序、大数据、云计算、物联网等领域都得到广泛应用

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

  • Server(Broker):接收客户端连接,实现AMQP协议的消息队列和路由功能的进程.
  • Virtual Host:虚拟主机的概念,类似权限控制组,一个Virtual Host里可以有多个Exchange和Queue.
  • Exchange:交换机,接收生产者发送的消息,并根据Routing Key将消息路由到服务器中的队列Queue.
  • ExchangeType:交换机类型决定了路由消息行为,RabbitMQ中有三种类型Exchange,分别是fanout、direct、topic.
  • Message Queue:消息队列,用于存储还未被消费者消费的消息.
  • Message:由Header和body组成,Header是由生产者添加的各种属性的集合,包括Message是否被持久化、优先级是多少、由哪个Message Queue接收等.body是真正需要发送的数据内容.
  • BindingKey:绑定关键字,将一个特定的Exchange和一个特定的Queue绑定起来.

 二. Docker安装部署RabbitMQ

 1.拉取镜像

注意获取镜像的时候要获取management版本的,不要获取last版本的,management版本的才带有管理界面

docker pull rabbitmq:management

2.安装

docker run -d \
--name my-rabbitmq \
-p 5672:5672 -p 15672:15672 \
-v /home/rabbitmq:/var/lib/rabbitmq \
--hostname my-rabbitmq-host \
-e RABBITMQ_DEFAULT_VHOST=my_vhost \
-e RABBITMQ_DEFAULT_USER=admin \
-e RABBITMQ_DEFAULT_PASS=admin \
--restart=always \
rabbitmq:management
  • -d:表示以后台(守护进程)模式运行容器。
  • --name my-rabbitmq:指定容器的名称为my-rabbitmq。
  • -p 5672:5672 -p 15672:15672:将主机的5672和15672端口映射到容器内对应的端口,其中5672是RabbitMQ的消息传递端口,15672是RabbitMQ的管理界面端口。
  • -v /home/rabbitmq:/var/lib/rabbitmq:将主机上的/home/rabbitmq目录挂载到容器内的/var/lib/rabbitmq目录,用于持久化存储RabbitMQ的数据。
  • --hostname my-rabbitmq-host:设置容器的主机名为my-rabbitmq-host。
  • -e RABBITMQ_DEFAULT_VHOST=my_vhost:设置RabbitMQ的默认虚拟主机为my_vhost。
  • -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin:设置默认用户名和密码为admin/admin。
  • --restart=always:设置容器在启动时自动重启。
  • rabbitmq:management:使用rabbitmq:management镜像来运行容器,该镜像包含了RabbitMQ及其管理插件

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

3.访问

然后就是访问了,但是在访问之前需要设置一下防火墙的相关配置...

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式防火墙设置好之后,开启那个rabbitmq的容器就好啦

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式现在就可以访问了

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

三.springboot连接配置

1.进入rabbitmq管理界面

然后输入密码之后就可以进入到里面啦

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

如果分不清页面上的东西,那么可以把这个页面翻译成中文的

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

2.创建用户

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

3.分配权限给用户

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

然后再退出登录,使用wh的这个账号登录一下

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

四.代码实现简单队列 

1.创建一个生产者模块

它的父项目是一个空项目,下面是这个生产者模块选择的依赖

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

server:
  port: 8888
spring:
    rabbitmq:
        host: 192.168.101.129
        username: wh
        password: 123456
        port: 5672
        virtual-host: my_vhost
        connection-timeout: 0

2.创建一个消费者模块

其中用到的依赖跟上面是一样的

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

server:
  port: 9999
spring:
  rabbitmq:
    host: 192.168.101.129
    password: 123456
    port: 5672
    username: wh
    virtual-host: my_vhost

3.代码操作

(1)配置RabbitMQ消息队列

package com.wh.publisher;

import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

// 使用@Configuration注解标记这是一个配置类
@Configuration
// 忽略所有警告
@SuppressWarnings("all")
public class RabbitConfig {
    // 定义一个名为firstQueue的方法,返回类型为Queue
    @Bean
    public Queue firstQueue() {
        // 创建一个新的Queue对象,名称为"firstQueue"
        return new Queue("firstQueue");
    }
}

(2)向消息队列发消息

package com.wh.publisher;

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author是辉辉啦
 * @create 2024-01-19-19:25
 */
@RestController
public class TestController {
    @Autowired
    private AmqpTemplate amqpTemplate;
   @RequestMapping("/send01")
    public String send01(){
       //像消息队列发送消息
       amqpTemplate.convertAndSend("firstQueue", "Hello World");
       return "😙😙";
   }
    @RequestMapping("/hh")
    public String hh(){
        //像消息队列发送消息
        return "😙😙";
    }
}

(3)连接rabbitmq测试

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

这时候就可以看到连接成功了

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

里面也多了一个新的队列

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

(4)RabbitMQ消息队列的消费者

package com.wh.consumer;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

// 定义一个名为Receiver的组件类,用于处理接收到的消息
@Component
// 抑制所有警告信息
@SuppressWarnings("all")
// 使用SLF4J日志框架进行日志记录
@Slf4j
// 监听名为"firstQueue"的队列
@RabbitListener(queues = "firstQueue")
public class Receiver {
    // 使用@RabbitHandler注解标记处理方法,该方法会在接收到消息时被调用
    @RabbitHandler
    public void process(String msg) {
        // 记录接收到的消息内容
        log.warn("接收到:" + msg);
    }
}

其中可以接收到生产者的消息

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

(5)成自定义数据发送

这个user对象生产者模块和消费者模块都要放置...如果觉得麻烦可以建一个公共项目放置dto

package com.wh.publisher;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.io.Serializable;

@SuppressWarnings("all")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private String username;
private String userpwd;
}
①配置RabbitMQ消息队列
package com.wh.publisher;

import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

// 使用@Configuration注解标记这是一个配置类
@Configuration
// 忽略所有警告
@SuppressWarnings("all")
public class RabbitConfig {
    // 定义一个名为firstQueue的方法,返回类型为Queue
    @Bean
    public Queue firstQueue() {
        // 创建一个新的Queue对象,名称为"firstQueue"
        return new Queue("firstQueue");
    }

    // 定义一个名为secondQueue的方法,返回类型为Queue
    @Bean
    public Queue secondQueue() {
        // 创建一个新的Queue对象,名称为"secondQueue"
        return new Queue("secondQueue");
    }
}
②RabbitMQ消息队列的消费者
package com.wh.consumer;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

// 定义一个名为Receiver的组件类,用于处理接收到的消息
@Component
// 抑制所有警告信息
@SuppressWarnings("all")
// 使用SLF4J日志框架进行日志记录
@Slf4j
// 监听名为"firstQueue"的队列
@RabbitListener(queues = "secondQueue")
public class ModelReceiver {
    // 使用@RabbitHandler注解标记处理方法,该方法会在接收到消息时被调用
    @RabbitHandler
    public void process(User user) {
        // 记录接收到的消息内容
        log.warn("接收到:" + user);
    }
}

成功

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

五.本篇问题总结

1.端口没开

在使用spring连接rabbitmq时,发现一直处于连接超时/拒绝连接的状态,后来发现是防火墙的端口没有开

启动防火墙

systemctl start firewalld

开放端口

firewall-cmd --zone=public --add-port=端口号/tcp --permanent

刷新防火墙规则

firewall-cmd --reload

查看防火墙列表

firewall-cmd --zone=public --list-ports

项目的端口以及rabbitmq的端口都需要开启

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

2.配置文件的层级关系

但是后面发现还是有问题,结果是配置文件的格式问题,这个rabbitmq是放在spring下面,一i的那个不要放错

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

3.配置文件中的信息核对

RabbitMQ入门篇【图文并茂,超级详细】,rabbitmq,分布式

  • server.port:指定了应用程序的HTTP端口号,这里设置为9999;
  • spring.rabbitmq.host:指定了RabbitMQ服务器的IP地址或主机名,这里设置为192.168.101.129;
  • spring.rabbitmq.usernamespring.rabbitmq.password:分别指定了连接RabbitMQ所使用的用户名和密码,这里设置为wh和123456;
  • spring.rabbitmq.port:指定了RabbitMQ服务的端口号,这里设置为5672;
  • spring.rabbitmq.virtual-host:指定了RabbitMQ的虚拟主机,以便在多个应用程序之间区分不同的队列和交换机,这里设置为my_vhost。

还有就是要检查好自己的用户名与密码是否是对的,还有就是RabbitMQ服务器的IP地址或主机名一定要写对【自己的RabbitMQ安装在哪里就填写哪个的地址】,以及配置文件里面的东西都需要核对清楚

好啦,今天的分享就到这了,希望能够帮到你呢!😊😊 文章来源地址https://www.toymoban.com/news/detail-808263.html

到了这里,关于RabbitMQ入门篇【图文并茂,超级详细】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 从0到1阿里云部署mysql8数据库(外网可访问)(图文并茂超详细)

    目录 一,下载MYSQL安装和配置  二,外网连接阿里云数据库 1.切换到 /app/soft/ 2.创建mysql文件夹 3.切换到mysql文件夹下 4,下载mysql8.0安装包,等待下载成功 5,解压mysql8.0安装包  6,重命名解压出来的文件夹,这里改成mysql-8.0  7,mysql-8.0文件夹下创建data文件夹 存储文件 8,分别

    2024年02月02日
    浏览(38)
  • 新电脑的正确打开方式——(近万字图文并茂详细分步骤讲解)【万一那天你就有新电脑了呢】包括个性化·等你来解锁哦

    新电脑买回来如何让配置?新电脑买回来如何装饰?新电脑买回来如何让电脑更干净?等等,这些问题都在困惑着大家,那么接下来我急来告诉大家——新电脑的正确打开方式吧!🎊 建议收藏此博客,万一那天你也有属于自己的新机了呢😁 似此星辰非昨夜,为谁风露立中宵

    2024年02月09日
    浏览(39)
  • Activiti7(图文并茂)

    Activiti 是由 jBPM (BPM,Business Process Management 即业务流程管理) 的创建者 Tom Baeyens 离开 JBoss 之后建立的项目,构建在开发 jBPM 版本 1 到 4 时积累的多年经验的基础之上,旨在创建下一代的 BPM 解 决方案。 Activiti 作为一个开源的工作流引擎,它实现了BPMN 2.0规范,可以发布设计

    2024年02月06日
    浏览(37)
  • secureCRT安装和使用教程【图文并茂】

    简介 一般而言,嵌入式开发板使用串口来监控后台。可以使用串口线连接开发板和电脑,对于没有串口的笔记本电脑来说,一般还需要一根USB转串口线。 串口线 串口软件多种多样,比如secureCRT、Xshell、超级终端、miniCom、putty等,它们的功能大同小异,因此只需安装用的顺手

    2024年02月03日
    浏览(71)
  • 发送图文并茂的html格式的邮件

    本文介绍如何生成和发送包含图表和表格的邮件,涉及echarts图表转换为图片、图片内嵌到html邮件内容中、html邮件内容生成、邮件发送方法等 因为html格式的邮件不支持echarts,也不支持js执行,所以图表需要转换为图片内嵌在邮件内容中 因为平台首页相关统计都是使用echarts渲

    2024年02月11日
    浏览(29)
  • 归并排序Java版(图文并茂思路分析)

    工作原理是将一个大问题分解成小问题,再将小问题分解成更小的。(乍一看就觉得是像一个递归)就像下图这样。然后不断的将其一份为二,分解成更小的排序。 我们设一个函数叫MergeSort(arr,l,r)意思就是将arr数组下标为[ l ,r ]之间的数进行排序。 那么就开始不断的

    2024年02月06日
    浏览(30)
  • Java 线程池详解,图文并茂,还有谁不会?!

    来源:blog.csdn.net/mu_wind/article/details/113806680 我们知道,线程的创建和销毁都需要映射到操作系统,因此其代价是比较高昂的。出于避免频繁创建、销毁线程以及方便线程管理的需要,线程池应运而生。 降低资源消耗 :线程池通常会维护一些线程(数量为 corePoolSize),这些线

    2024年02月06日
    浏览(33)
  • 什么是感知机——图文并茂,由浅入深

    生活中常常伴随着各种各样的逻辑判断,比如看到远方天空中飘来乌云,打开手机看到天气预报说1小时后40%的概率下雨,此时时候我们常常会做出等会下雨,出门带伞的判断。 上述思考过程可以抽象为一个”与“的”神经逻辑“。当”看到乌云“和”天气预报40%下雨“同时

    2023年04月20日
    浏览(27)
  • Flutter 图文并茂:打造交互丰富的应用界面

    Flutter作为一种现代的UI工具包,为开发者提供了丰富的工具和小部件,轻松构建漂亮、响应迅速的应用界面。本篇博客将带你踏入Flutter的世界,学习如何巧妙运用图片、按钮、图标,以及行与列进行布局,打造令人惊艳的用户交互体验。 无论你是Flutter初学者还是有一定经验

    2024年02月03日
    浏览(27)
  • NodeMCU ESP8266开发流程详解(图文并茂)

    NodeMCU ESP8266基于Arduino IDE的开发相对来说还是比较容易上手的,我们基本需要以下几个东西; 一台安装好Arduino IDE的PC,并且已经部署环境(安装好开发板的串口驱动); NodeMCU ESP8266 开发板; USB线(根据实际开发板的情况,本文需要Micro-USB的线); 具体如下图所示; 本文默

    2024年02月06日
    浏览(38)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包