【Spring Cloud】Sentinel流量限流和熔断降级的讲解

这篇具有很好参考价值的文章主要介绍了【Spring Cloud】Sentinel流量限流和熔断降级的讲解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

🎉🎉欢迎来到我的CSDN主页!🎉🎉

🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚

🌟推荐给大家我的专栏《Spring Cloud》。🎯🎯

👉点击这里,就可以查看我的主页啦!👇👇

Java方文山的个人主页

🎁如果感觉还不错的话请给我点赞吧!🎁🎁

💖期待你的加入,一起学习,一起进步!💖💖

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

目录

前言

服务雪崩效应

一、常见的容错方案

二、Sentinel入门

1.什么是Sentinel

2.Sentinel 分为两个部分

3.微服务集成Sentinel

三、安装Sentinel控制台

实现一个接口的限流

四、Sentinel规则

流控规则

①简单配置

②配置流控模式

③链路流控模式

配置流控效果

五、Feign整合Sentinel

前言

在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用,但是由于网络原因或者自身的原因,服务并不能保证服务的100%可用,如果单个服务出现问题,调用这个服务就会出现网络延迟,此时若有大量的网络涌入,会形成任务堆积,最终导致服务瘫痪(雪崩)。

接下来,我们来模拟一个高并发的场景

①编写java代码

@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private IFeignProductService feignProductService;

    @RequestMapping("/findByParameter")
    public String findByParameter(String name,Double price){
        log.info("服务消费者日志:name={},price={}",name,price);
        return feignProductService.findByParameter(name,price);
    }
}

②修改配置文件中tomcat的并发数

1秒钟20个请求,最大连接数10,最大等待数10,最大线程数2,相当于一个线程1s能处理5个请求(2个处理10个请求)

server:
  port: 8091
  tomcat:
    max-threads: 2     #最大线程数
  max-connections: 10  #最大连接数
  accept-count: 10     #最大线程等待数

如果我1s发送5个以上的请求,此时会发现, 由于order方法囤积了大量请求, 导致message方法的访问出现了问题,这就是服务雪崩的雏形。

服务雪崩效应

在分布式系统中,由于网络原因或自身的原因,服务一般无法保证 100% 可用。如果一个服务出现了 问题,调用这个服务就会出现线程阻塞的情况,此时若有大量的请求涌入,就会出现多条线程阻塞等 待,进而导致服务瘫痪。 由于服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是 服务故障的 “雪崩效应” 。

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

雪崩发生的原因多种多样,有不合理的容量设计,或者是高并发下某一个方法响应变慢,亦或是某 台机器的资源耗尽。我们无法完全杜绝雪崩源头的发生,只有做好足够的容错,保证在一个服务发生问 题,不会影响到其它服务的正常运行。也就是"雪落而不雪崩"。  

一、常见的容错方案

要防止雪崩的扩散,我们就要做好服务的容错,容错说白了就是保护自己不被猪队友拖垮的一些措 施, 下面介绍常见的服务容错思路和组件。 常见的容错思路 常见的容错思路有隔离、超时、限流、熔断、降级这几种,下面分别介绍一下。

  • 隔离 它是指将系统按照一定的原则划分为若干个服务模块,各个模块之间相对独立,无强依赖。当有故障发生时,能将问题和影响隔离在某个模块内部,而不扩散风险,不波及其它模块,不影响整体的系统服务。常见的隔离方式有:线程池隔离和信号量隔离。

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

  • 超时 在上游服务调用下游服务的时候,设置一个最大响应时间,如果超过这个时间,下游未作出反应,就断开请求,释放掉线程。

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

  • 限流 限流就是限制系统的输入和输出流量已达到保护系统的目的。为了保证系统的稳固运行,一旦达到 的需要限制的阈值,就需要限制流量并采取少量措施以完成限制流量的目的。

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

  • 熔断 在互联网系统中,当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整 体的可用性,可以暂时切断对下游服务的调用。这种牺牲局部,保全整体的措施就叫做熔断

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

服务熔断一般有三种状态:

  • 熔断关闭状态(Closed) 服务没有故障时,熔断器所处的状态,对调用方的调用不做任何限制
  • 熔断开启状态(Open) 后续对该服务接口的调用不再经过网络,直接执行本地的fallback方法
  • 半熔断状态(Half-Open) 尝试恢复服务调用,允许有限的流量调用该服务,并监控调用成功率。如果成功率达到预期,则说明服务已恢复,进入熔断关闭状态;如果成功率仍旧很低,则重新进入熔断启动状态。
  • 降级 降级其实就是为服务提供一个托底方案,一旦服务无法正常调用,就使用托底方案。

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

常见的容错组件

  • Hystrix Hystrix是由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或者第三方库,防止 级联失败,从而提升系统的可用性与容错性。

  • Resilience4J Resilicence4J一款非常轻量、简单,并且文档非常清晰、丰富的熔断工具,这也是Hystrix官方推 荐的替代产品。不仅如此,Resilicence4j还原生支持Spring Boot 1.x/2.x,而且监控也支持和 prometheus等多款主流产品进行整合。

  • Sentinel Sentinel 是阿里巴巴开源的一款断路器实现,本身在阿里内部已经被大规模采用,非常稳定。

    下面是三个组件在各方面的对比:

Sentinel Hystrix
隔离策略 信号量隔离 线程池隔离/信号量隔离
熔断降级策略 基于响应时间或失败比率 基于失败比率
实时指标实现 滑动窗口 滑动窗口(基于 RxJava)
规则配置 支持多种数据源 支持多种数据源
扩展性 多个扩展点 插件的形式
基于注解的支持 即将支持 支持
限流 基于 QPS,支持基于调用关系的限流 不支持
流量整形 支持慢启动、匀速器模式 不支持
系统负载保护 支持 不支持
控制台 开箱即用,可配置规则、查看秒级监控、机器发现等 不完善
常见框架的适配 Servlet、Spring Cloud、Dubbo、gRPC 等 Servlet、Spring Cloud Netflix

二、Sentinel入门

1.什么是Sentinel

Sentinel (分布式系统的流量防卫兵) 是阿里开源的一套用于服务容错的综合性解决方案。它以流量 为切入点, 从流量控制、熔断降级、系统负载保护等多个维度来保护服务的稳定性。 Sentinel 具有以下特征:

  • 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景, 例如秒杀(即 突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。

  • 完备的实时监控:Sentinel 提供了实时的监控功能。通过控制台可以看到接入应用的单台机器秒 级数据, 甚至 500 台以下规模的集群的汇总运行情况。

  • 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块, 例如与 Spring Cloud、Dubbo、gRPC 的整合。只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。

  • 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

2.Sentinel 分为两个部分

  • 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。

  • 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等 应用容器。

3.微服务集成Sentinel

为微服务集成Sentinel非常简单, 只需要加入Sentinel的依赖即可,在需要的模块pom.xml中加入下面依赖

<!--sentinel-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

网关gateway集成sentinel,需还另添加以下依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>

另外编写一个Controller测试使用

(我这里就直接用我之前讲解组件所写的生产服务和消费服务做模拟,以下是我生产服务的代码)

@RestController
public class ProduceController {
    @RequestMapping("/run")
    public String run() {
        return "🍗";
    }
}

三、安装Sentinel控制台

Sentinel 提供一个轻量级的控制台, 它提供机器发现、单机资源实时监控以及规则管理等功能。

①下载jar包,解压到文件夹 Releases · alibaba/Sentinel · GitHub

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

②启动控制台

# 直接使用jar命令启动项目(控制台本身是一个SpringBoot项目)
java -Dserver.port=9999 -Dcsp.sentinel.dashboard.server=localhost:9999 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.7.0.jar

#参考1
java -jar sentinel-dashboard-1.8.1.jar --server.port=8080
#参考2
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.1.jar

③修改shop-order ,在里面加入有关控制台的配置

   sentinel:
      transport:
        port: 8719
        dashboard: localhost:9999
      eager: true
      web-context-unify: false

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

④通过浏览器访问localhost:9999进入控制台 ( 默认用户名密码是 sentinel/sentinel )

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

 补充:

了解控制台的使用原理 Sentinel的控制台其实就是一个SpringBoot编写的程序。我们需要将我们的微服务程序注册到控制台上,即在微服务中指定控制台的地址, 并且还要开启一个跟控制台传递数据的端口, 控制台也可以通过此端口调用微服务中的监控程序获取微服务的各种信息。一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

实现一个接口的限流

1 通过控制台为message1添加一个流控规则

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

2 通过控制台快速频繁访问, 观察效果

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

四、Sentinel规则

流控规则

流量控制,其原理是监控应用流量的QPS(每秒查询率) 或并发线程数等指标,当达到指定的阈值时 对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。 第1步: 点击簇点链路,我们就可以看到访问过的接口地址,然后点击对应的流控按钮,进入流控规则配置页面。新增流控规则界面如下:

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

资源名:唯一名称,默认是请求路径,可自定义 针对来源:指定对哪个微服务进行限流,默认指default,意思是不区分来源,全部限制 阈值类型/单机阈值

  • QPS(每秒请求数量): 当调用该接口的QPS达到阈值的时候,进行限流

  • 线程数:当调用该接口的线程数达到阈值的时候,进行限流

是否集群:暂不需要集群 接下来我们以QPS为例来研究限流规则的配置。

①简单配置

我们先做一个简单配置,设置阈值类型为QPS,单机阈值为3。即每秒请求量大于3的时候开始限流。 接下来,在流控规则页面就可以看到这个配置。

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

然后快速访问/order/message1 接口,观察效果。此时发现,当QPS > 3的时候,服务就不能正常响应,而是返回Blocked by Sentinel (flow limiting)结果。

配置流控模式

点击上面设置流控规则的编辑按钮,然后在编辑页面点击高级选项,会看到有流控模式一栏。

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

sentinel共有三种流控模式,分别是:

  • 直接(默认):接口达到限流条件时,开启限流

  • 关联:当关联的资源达到限流条件时,开启限流 [适合做应用让步]

  • 链路:当从某个接口过来的资源达到限流条件时,开启限流

 下面呢分别演示三种模式:

直接流控模式 直接流控模式是最简单的模式,当指定的接口达到限流条件时开启限流。上面案例使用的就是直接流控模式。

关联流控模式 关联流控模式指的是,当指定接口关联的接口达到限流条件时,开启对指定接口开启限流。

第1步:配置限流规则, 将流控模式设置为关联,关联资源设置为的 /run2。

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

第3步:通过produce软件向/run2连续发送请求,注意QPS一定要大于3

第4步:访问/run2,会发现已经被限流

链路流控模式

链路模式是Sentinel流量控制框架中的一种模式,用于对特定的请求链路进行限流。在一个复杂的系统中,请求可能会经过多个服务或接口的调用链,而其中的某一个接口可能会成为整个链路的瓶颈,导致系统性能下降或者不可用。链路模式允许在该接口的流量达到限制条件时进行限流,以保护整个链路的稳定性。

第1步: 编写一个service,在里面添加一个方法message

@Service
 class OrderServiceImpl2 {
    @SentinelResource("message")
    public void message() {
    	System.out.println("message");
    }
}

第2步: 在Controller中声明两个方法,分别调用service中的方法message

@RestController
@Slf4j
public class OrderController5 {
    @Autowired
    private OrderServiceImpl2 orderService;
    @RequestMapping("/order/message1")
    public String message1() {
        orderService.message();
        return "message1";
	}
    @RequestMapping("/order/message2")
    public String message2() {
        orderService.message();
        return "message2";
    }
}

第3步:配置文件中将spring.cloud.sentinel.web-context-unify=true即可开启收敛

在 Web 应用中,同一个请求可能会有多种不同的 URL 地址和 HTTP 方法,例如 GET /user 和 POST /user 是两个不同的请求,但它们都是对用户资源的操作。如果不统一这些请求,会导致资源的重复计数,从而影响限流效果。因此,通过设置 web-context-unifytrue,Sentinel 可以将这些不同的请求统一为同一个资源,并对其进行流量控制。

 第4步: 控制台配置限流规则

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring 第5步: 分别通过/order/message1 和/order/message2 访问, 发现1没问题, 2的被限流了

配置流控效果

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

  • 快速失败(默认): 直接失败,抛出异常,不做任何额外的处理,是最简单的效果
  • Warm Up:它从开始阈值到最大QPS阈值会有一个缓冲阶段,一开始的阈值是最大QPS阈值的 1/3,然后慢慢增长,直到最大阈值,适用于将突然增大的流量转换为缓步增长的场景。
  • 排队等待让请求以均匀的速度通过,单机阈值为每秒通过数量,其余的排队等待; 它还会让设 置一个超时时间,当请求超过超时间时间还未处理,则会被丢弃。

 

五、Feign整合Sentinel

①导入依赖

 <dependency>
       <groupId>com.alibaba.cloud</groupId>
       <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
 </dependency>

  ②在配置文件中开启Feign对Sentinel的支持

# 开启feign对sentinel的支持
feign:
  sentinel:
    enabled: true

   ③创建容错类

@Component
public class FeignUserServiceImpl implements FeignUserService {
    //容错类要求必须实现被容错的接口,并为每个方法实现容错方案
    @Override
    public String getByPath(String account) {
        //写入到自己的数据估值表中
        //程序员看到就会来处理
        return "容错类启动......";
    }

}

④为被容器的接口指定容错类

@FeignClient(value = "produce" ,fallback = FeignUserServiceImpl.class)
@Primary
public interface FeignUserService {

    @RequestMapping("/user/{account}")
    public String getByPath(@PathVariable(value = "account") String account);

}

在Spring Cloud中,使用Feign进行服务间的调用时,可以通过设置fallback属性来指定当请求失败或超时时的容错处理类。fallback属性是一个接口的实现类,它会在调用失败时被触发,以提供一个备用的处理逻辑。 

当我们正常调用localhost:8084/test01的时候就会响应相应的结果

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

如果我们访问的模块服务宕机了就会跳转到我们的容错类

 一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

我们容错类就会将请求信息进行保存等待我们模块服务正常后重新发送请求 

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring

到这里我的分享就结束了,欢迎到评论区探讨交流!!

💖如果觉得有用的话还请点个赞吧 💖

一个接口可以多个sentinel限流规则么,# Spring Cloud,spring cloud,sentinel,spring文章来源地址https://www.toymoban.com/news/detail-819095.html

到了这里,关于【Spring Cloud】Sentinel流量限流和熔断降级的讲解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • SpringCloud学习6(Spring Cloud Alibaba)断路器Sentinel熔断降级

    SpringCloud学习6(Spring Cloud Alibaba)断路器Sentinel熔断降级

    SpringCloud、SpringCloudAlibaba、SpringBoot版本选择。为了避免各种千奇百怪的bug,我们还是采用官方推荐的毕业版本。 修改tomcat配置最大线程数 引入测试依赖 编写测试代码 这里同时我们在浏览器去请求该地址,响应会变得很慢 测试结论:此时会发现由于thread接口囤积大量请求,

    2023年04月08日
    浏览(18)
  • Sentinel 降级、限流、熔断

    Sentinel 降级、限流、熔断

    在现代分布式系统中,如何有效地保护系统免受突发流量和故障的影响,是每个开发人员和架构师都需要思考的重要问题。在这样的背景下,Sentinel作为一个强大的系统保护和控制组件,为我们提供了降级、限流、熔断等多种策略,帮助我们更好地保障系统的稳定性和可用性

    2024年01月24日
    浏览(11)
  • 【Spring Cloud Alibaba】Sentinel 服务熔断与流量控制

    【Spring Cloud Alibaba】Sentinel 服务熔断与流量控制

    目录 前言 一、Sentinel 入门 1.1 什么是 Sentinel ? 1.2 微服务集成 Sentinel  1.3 安装Sentinel控制台 二、Jmeter 压力测试工具 2.1 Jmeter 介绍  2.2 Jmeter 安装 2.3 接口测试 三、Sentinel 使用 3.1 限流规则 3.1.1 warm up(预热模式) 3.1.2 排队等待 3.1.3 关联 3.1.4 链路 3.2 熔断规则 3.3 服务降级     

    2024年02月01日
    浏览(11)
  • 熔断、限流、降级 —— SpringCloud Alibaba Sentinel

    熔断、限流、降级 —— SpringCloud Alibaba Sentinel

    Sentinel 是阿里中间件团队开源的,面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性 Sentinel 提供了两个服务组件: Sentinel 用来实现微服务系统中服务熔断

    2024年02月08日
    浏览(36)
  • Sentinel流量控制与熔断降级

    Sentinel流量控制与熔断降级

    📝 学技术、更要掌握学习的方法,一起学习,让进步发生 👩🏻 作者:一只IT攻城狮 ,关注我,不迷路 。 💐学习建议:1、养成习惯,学习java的任何一个技术,都可以先去官网先看看,更准确、更专业。 💐学习建议:2、然后记住每个技术最关键的特性(通常一句话或者

    2024年02月10日
    浏览(14)
  • 实战:Springboot集成Sentinel实现流量控制、熔断降级、负载保护

    实战:Springboot集成Sentinel实现流量控制、熔断降级、负载保护

    前面的文章我们学习了Hystrix并和springboot项目进行了集成,实现服务的熔断降级、隔离措施。但是Hystrix对流量的控制不是很好,仅仅信号量也只能对指定的接口进行限流,至于保护机制Hystrix也只是达到指标进行熔断。那么,有没有一种中间件可以在兼容熔断降级的同时精准实

    2024年02月16日
    浏览(10)
  • 商城-学习整理-高级-商城业务-Sentinel&限流&熔断&降级&Sleuth+Zipkin链路追踪(二十二)

    商城-学习整理-高级-商城业务-Sentinel&限流&熔断&降级&Sleuth+Zipkin链路追踪(二十二)

    什么是熔断 A 服务调用 B 服务的某个功能,由于网络不稳定问题,或者 B 服务卡机,导致功能时间超长。如果这样子的次数太多。我们就可以直接将 B 断路了(A 不再请求 B 接口),凡是调用 B 的直接返回降级数据,不必等待 B 的超长执行。 这样 B 的故障问题,就不会级联影

    2024年02月11日
    浏览(10)
  • 聊一聊服务治理三板斧:限流、熔断、降级和go-sentinel的实现

    聊一聊服务治理三板斧:限流、熔断、降级和go-sentinel的实现

    我们知道,对于一个项目之初,我们不可能上来就按几千的并发去配置,为什么?两个方面,第一个是成本高。第二个是维护难度大。即便是天猫淘宝这种,也是采用的动态扩容的方式来应对双十一。那么一个项目如何应对突然的高并发,我们有哪些常用的措施和处理呢?我

    2024年01月19日
    浏览(15)
  • 【微服务笔记21】微服务组件之Sentinel服务熔断、服务降级、流量控制介绍

    【微服务笔记21】微服务组件之Sentinel服务熔断、服务降级、流量控制介绍

    这篇文章,主要介绍微服务组件之Sentinel服务熔断、服务降级、流量控制。 目录 一、Sentinel组件 1.1、Sentinel介绍 1.2、Sentinel环境搭建 (1)引入依赖 (2)资源和规则 1.3、使用SphU定义资源 (1)定义资源 (2)定义规则 1.4、使用SphO定义资源 (1)定义资源 (2)定义规则 1.5、

    2024年04月17日
    浏览(14)
  • Spring Cloud GateWay实现熔断降级

    当分布式系统中的网关接收到大量请求并向后端远程系统或服务发起调用时,后端服务可能会产生调用失败(如超时或异常)。这时,如果让请求继续堆积在网关上,可能会导致整个系统的瘫痪。因此,需要快速失败并返回请求,这就是所谓的熔断。 降级是指在系统资源不足

    2024年02月02日
    浏览(7)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包