SpringCloudAlibaba

课程内容

  • SpringCloudAlibaba介绍

  • Nacos服务注册与发现

  • Nacos配置中心

  • Sentinel限流

  • Sentinel熔断

一.SpringCloudAlibaba介绍

1.SpringCloudAlibaba认识

1.1.为什么会出现SpringCloudAlibaba

早期在国内做分布式(微服务)应用Dubbo是比较热门的框架,被许多互联网公司所采用,并产生了许多衍生版本,如网易,京东,新浪,当当等等,奈何在2014年10月Dubbo停止维护,在Dubbo停更的时间里Spring Cloud快速追赶上。在2017年9月,阿里宣布重启Dubbo项目,计划对Dubbo进行持续更新维护。2018.2月,阿里将Dubbo捐献给Apache基金会,Dubbo成为Apache孵化器项目。

所以当前微服务架构,Dubbo和SpringCloud比较火,另外还有Thrift、gRPC等等 。很多人把SpringCloud 和Dubbo进行对比,其实两个框架并没有太大的可比性,因为他们的定位不同。Spring Cloud是一个完整的微服务解决方案,它提供了微服务各问题的解决方案集合,而Dubbo是一个高性能的RPC框架,它有着很多功能的缺失。

但是很多企业一边想要Dubbo的高性能RPC ,一边又想要Spring Cloud 完整的生态,然后在项目中出现了两个微服务框架的身影 。甚至市面上出现了一些Dubbo和Sprng Cloud的融合方案,但是最终都不是特别成熟。直到Spring Cloud官方出现了Spring Cloud Alibaba 才算是吧Dubbo和Spring Cloud真正的融合在一起。

1.2.什么是 Spring Cloud Alibaba

下面是Spring Cloud 官方对Spring Cloud Alibaba的介绍

Spring Cloud Alibaba旨在为微服务开发提供一站式解决方案。该项目包括开发分布式应用程序和服务所需的组件,以便开发人员可以使用Spring Cloud编程模型轻松开发分布式应用程序。使用Spring Cloud Alibaba,您只需要添加一些注释和配置,就可以为您的应用程序使用Alibaba的分布式解决方案,并使用Alibaba中间件构建自己的分布式系统。

Spring Cloud Alibaba其实是阿里的微服务解决方案,是阿里巴巴结合自身微服务实践,开源的微服务全家桶,在Spring Cloud项目中孵化成为Spring Cloud的子项目。第一代的Spring Cloud标准中很多组件已经停更,如:Eureak,zuul等。所以Spring Cloud Alibaba很有可能成为Spring Cloud第二代的标准实现,所以许多组件在业界逐渐开始使用,已有很多成功案例。

值得一提的是Spring Cloud Alibaba对Dubbo做了很好的兼容,同时也提供了一些强大的功能,如 Sentinel 流控 ,Seata 分布式事务,Nacos 服务发现与注册等等。

Spring Cloud Alibaba的功能

Spring Cloud Alibaba是阿里巴巴结合自身的微服务实践开源的微服务全家桶,我个人觉得其组件比Spring Cloud 中的组件更加好用和强大。并且对的Spring Cloud组件做了很好的兼容。比如在Spirng Cloud Alibaba中依然可以使用Feign作为服务调用方式,使用Eureak做服务注册发现等等。Spring Cloud Alibaba主要的功能如下:

  • 流控制和服务降级:支持WebServlet,WebFlux,OpenFeign,RestTemplate,Dubbo访问限制和降级流的功能。它可以在运行时通过控制台实时修改限制和降级流的规则,并且还支持监视限制和降级度量标准。

  • 服务注册和发现:可以注册服务,并且客户可以使用Spring托管的bean(自动集成功能区)发现实例。

  • 分布式配置:支持分布式系统中的外部配置,配置更改时自动刷新。

  • Rpc服务:扩展Spring Cloud客户端RestTemplate和OpenFeign以支持调用Dubbo RPC服务。

  • 事件驱动:支持构建与共享消息系统连接的高度可扩展的事件驱动微服务。

  • 分布式事务:支持高性能且易于使用的分布式事务解决方案。

  • 阿里云对象存储:大规模,安全,低成本,高度可靠的云存储服务。支持随时随地在任何应用程序中存储和访问任何类型的数据。

  • 阿里云SchedulerX:准确,高度可靠,高可用性的计划作业调度服务,响应时间在几秒钟内。

  • 阿里云短信:阿里云短信服务覆盖全球,提供便捷,高效,智能的通信功能,帮助企业快速联系客户。

2.SpringCloud和SpringCloudAlibaba

2.1.两代技术对比

下面是SpringCloud 和 Spring Cloud Alibaba(命名 Dubbo Spring Cloud )的功能对比

功能组件Spring CloudDubbo Spring Cloud
分布式配置(Distributed configuration)Git、Zookeeper、Consul、JDBCSpring Cloud 分布式配置 + Dubbo 配置中心(Nacos)
服务注册与发现(Service registration and discovery)Eureka、Zookeeper、ConsulSpring Cloud 原生注册中心 + Dubbo 原生注册中心(Nacos)
负载均衡(Load balancing)Ribbon(随机、轮询等算法)Dubbo 内建实现(随机、轮询等算法 + 权重等特性)
服务熔断(Circuit Breakers)Spring Cloud HystrixSpring Cloud Hystrix + Alibaba Sentinel 等
服务调用(Service-to-service calls)Open Feign、RestTemplateSpring Cloud 服务调用 + Dubbo @Reference
链路跟踪(Tracing)Spring Cloud Sleuth + ZipkinZipkin、opentracing 等
2.2.Spring Cloud Alibaba的版本

Spring Cloud Alibaba是Spring Cloud的子项目 ,Spring Cloud 基于Spring Boot,所以我们在选择版本的时候需要考虑三个框架的版本,目前官方给出的版本如下:

Spring Cloud VersionSpring Cloud Alibaba VersionSpring Boot Version
Spring Cloud Greenwich2.1.x.RELEASE2.1.x.RELEASE
Spring Cloud Finchley2.0.x.RELEASE2.0.x.RELEASE
Spring Cloud Edgware1.5.x.RELEASE1.5.x.RELEASE

二.Nacos服务注册与发现

1.Nacos认识与安装

1.1.什么是Nacos

《Spring Cloud 极简入门》中我们学习了netflix 的 Eureka 组件作为微服务的服务发现。Nacos和Eureka有着相同的能力,甚至更为强大,作为Dubbo 生态系统中重要的注册中心实现。官方对它有如下定义:

Nacos致力于帮助您发现,配置和管理微服务。它提供了一组简单有用的功能,使您能够实现动态服务发现,服务配置,服务元数据和流量管理。Nacos使构建,交付和管理微服务平台变得更容易,更快捷。它是通过微服务或云原生方法支持以服务为中心的现代应用程序体系结构的基础架构。

这里我们看到Nacos不仅是服务发现组件,同时也是一个配置管理组件,也就是说它不仅可以用来取代Eureak作为注册中心, 也可以用来取代Spring Cloud Config 做配置统一管理。本篇文章意在探讨Nacos的服务注册与发现功能。

1.2.Nacos服务安装

官方提供了Nacos的服务端供我们下载使用,我们启动Nacos后将我们的微服务注册进入Nacos即可。

下载地址:Releases · alibaba/nacos · GitHub

启动Nacos:解压后,

  • windows执行bin目录下的startup命令 :startup.cmd -m standalone

  • linux 执行 :sh startup.sh -m standalone

访问Nacos,端口8848:http://127.0.0.1:8848/nacos/index.html ,用户名和密码都是:nacos 

登录成功之后

1.3.基于数据库持久化Nacos

找到nacos安装目录config/application.properties 文件,编辑数据库信息,修改内容如下

spring.datasource.platform=mysql
​
### Count of DB:
db.num=1
​
### Connect URL of DB:
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos-config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=123456

找到config/ nacos-mysql.sql 文件 ,创建数据库 nacos-config,然后导入该sql脚本文件

2.项目结构搭建

2.1.服务调用流程

我们这里要演示的案例是两个服务的通信,用户服务(user-server)作为服务提供者需要编写接口返回User实体对象,订单服务(order-server)作为消费者需要调用用户服务获取User实体对象,浏览器调用订单服务,订单服务调用用户服务或到User实体后返回给容器,用户和订单都注册到Nacos中,如下: 注意:这里的订单服务和用户服务都用到了User实体,所以为了让User实体共用,我们为User实体抽取了一个公共的user-common模块,用户服务和订单服务都去依赖这个模块即可使用User实体。

2.2.项目结构搭建

我们根据上面的图例来搭建项目环境,这里使用多模块方式演示,搭建父工程,提供者服务,消费者服务,以及公共的user-common模块,结构如下:

springcloudalibaba-parent
pom.xml
    springcloudalibaba-user-common          //公共的user实体,服务调用传输对象
    springcloudalibaba-order-server-1020    //消费者服务
    springcloudalibaba-user-server-1010     //提供者服务

父工程搭建搭建父工程springcloudalibaba-parent并管理相关依赖,Spring boot版本为2.1.3.RELEASE,Spring Cloud 版本为Greenwich.SR1,Alibaba版本为2.1.0.RELEASE ,父工程的pom如下:

<!--公共的一些配置-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        
    </properties>
​
   <!--SpringBoot-->
    <parent>
        <groupId> org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
    </parent>
​
    <!--SpringCloud-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.1.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

3.服务注册到Nacos(重要)

3.1.导入依赖

修改springcloudalibaba-user-server-1010导入服务发现依赖

 <dependency>
     <groupId>com.alibaba.cloud </groupId>
     <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--加入WEB依赖是为了方便后面写Controller-->
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
</dependency>
3.2.主配置类

创建配置类加上@EnableDiscoveryClient注解开启服务发现功能,代码如下

//服务注册与发现
@SpringBootApplication
@EnableDiscoveryClient
public class UserServerApplication1010 {
    public static void main(String[] args) {
        SpringApplication.run(UserServerApplication1010.class) ;
    }
}
3.3.配置文件

配置文件主要配置端口,服务名,已经nacos注册中心地址

server:
  port: 1010
spring:
  application:
    name: user-server
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 #注册中心地址
3.4.启动测试

启动服务提供者,观察Nacos服务列表 , user-server已经注册进去了 

4.服务通信

服务通信可以使用Ribbon,OpenFeign,甚至Dubbo,使用方式和在SpirngCloudNetflix中没有任何区别。

三.Nacos配置管理

1.Nacos配置中心

1.1.概述

在《SpringCloud极简入门》中我们通过Spring Cloud Config作为统一配置文件管理中心,其实我们总结一下发现Spring Cloud Config使用起来总归比较麻烦。Nacos作为Spring Cloud Alibaba的一个重要组件,它不仅可以用作服务注册与发现,也可以用来替代Spring Cloud Config作为统一配置文件管理,而且他的使用更为简单和人性化。

1.2.Nacos添加配置

第一步:打开Nacos监控面板 - 进入配置列表 -点击 “+” 图标添加配置 如下: 

第二步:填写Data ID,选择YAML,编辑配置文件内容

这里定义了一个名字为application-user-dev.yaml的配置,使用的是YAML格式。

  • Data ID : 非常重要,可以看做是配置的文件的名字,在程序中拉取配置文件的时候需要指定Data ID。

  • Group : 分组,默认是 DEFAULT_GROUP , 可以针对不同的项目指定不同的配置组。

2.客户端接入配置中心(重要)

2.1.导入依赖

修改工程 springcloudalibaba-user-server-1010 ,添加配置中心依赖nacos-config,完整pom.xml如下。

 <dependencies>
        <!--        配置中心客户端-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        
        <!-- 服务注册与发现-->
        <dependency>
            <groupId>com.alibaba.cloud </groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
​
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>springcloudalibaba-user-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
2.2.编写Controller

下面的Controller用来做配置刷新测试,temp.notify对应了配置文件中的配置项目。@RefreshScope注解是用来做配置自动刷新。那么当我们修改了Nacos中的配置文件,Controller中读取到的配置temp.notify将会自动变化。

@RefreshScope  //刷新配置
@RestController
public class UserController {
​
    @Value("${temp.notify}")
    private String notify;
​
    @GetMapping("/user/{id}")
    public User getById(@PathVariable Long id){
        System.out.println("测试配置notify="notify);
        return new User(id,"zs:"+id, "我是zs");
    }
}
​
2.3.修改yml配置

注意,将原来的配置文件修改成bootstrap.yml,然后增加如下内容:

server:
  port: 1010
spring:
  profiles:
    active: dev
  application:
    name: user-server
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #注册中心
      config:
        server-addr: localhost:8848 #配置中心
        file-extension: yaml #配置文件格式
        prefix: application-user #配置前缀 ,默认使用sring.application.name
        group: DEFAULT_GROUP #默认分组
    
#如何查找配置文件:application-user + dev + yaml=application-user-dev.yaml 正好和Nacos配置的DataId一致

提示:客户端是如何从Nacos中找到配置文件的呢?

  • spring.cloud.nacos.config.server-addr :配置了Nacos的地址

  • spring.cloud.nacos.config.file-extension:指定了配置文件的格式为YAML,默认是properties,

  • spring.cloud.nacos.config.prefix:配置前缀,如果不配置前缀默认会把 服务名即spring.application.name的值作为前缀

  • spring.cloud.nacos.config.group :分组名,默认是DEFAULT_GROUP对应了Nacos配置中的Group

  • spring.profiles.active:配置了环境为dev .该配置可以实现多配置多环境管理

根据如上配置,那么config客户端会将:前缀+环境+后缀 拼接成的文件名“application-user-dev.yaml” 去Nacos上查找是否有对应Data ID的配置文件。

2.4.测试

启动Nacos,启动 springcloudalibaba-user-server-1010 工程 , 修改Nacos中的配置文件内容,然后访问 http://localhost:1010/user/11 ,观察控制台打印的 “notify”的值会发生变化。

2.5.注意细节
  • 云端配置文件的后缀应该是 yaml而不是yml

  • 客户端配置需要指定:spring.profiles.active=dev 环境名

  • 客户端配置 :前缀 + 环境名 + 后缀应该和云端配置文件的DataId一致

3.命名空间

命名空间可以用来隔离不同项目的配置文件,在Nacos中配置了命名空间后,那么Java客户端需要指定命名空间后才能拉取到该命名空间下的配置文件。

3.1.创建命名空间

修改Nacos,添加命名空间如下: 这里建立了一个名字为“test”的命名空间,点击确定,然后你需要关注一下命名空间的ID,这个是需要在Java客户端进行配置的。如下: 

3.2.在命名空间创建配置

进入配置列表 ,切换到新建立的命名空间“test”,然后创建配置,如下: 需要注意后缀是yaml 

需要注意:这里的配置文件名也叫 application-user-dev.yaml,但是他是属于 “test”这个命名空间的 , 我们之前在 默认的“public”命名空间中也有一个同名的配置。

3.3.客户端配置

这里需要指定一下从哪个命名空间拉取配置:

server:
  port: 1010
spring:
  profiles:
    active: dev
  application:
    name: user-server
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #注册中心
      config:
        server-addr: localhost:8848 #配置中心
        file-extension: yaml #配置文件格式
        prefix: application-user #配置前缀 ,默认使用sring.application.name
        group: DEFAULT_GROUP #默认分组
        namespace: 8ef8c1e5-6d20-4efc-80c8-2b2c05541fa3 #命名空间的ID

注意:这里的namespace对应了 Nacos中“test”这个命名空间的ID,意思是从“test”这个命名空间去找 application-user-dev.yaml的配置文件。

3.4.启动测试

启动Nacos,启动 springcloudalibaba-user-server-1010 工程 , 修改Nacos中的配置文件内容,然后访问 http://localhost:1010/user/11 ,观察控制台打印的 “notify”的值

4.扩展需求

4.1.如何自定义Data ID

支持自定义扩展的 Data Id 配置 :Nacos config · alibaba/spring-cloud-alibaba Wiki · GitHub

4.2.开启Nacos认证

开启Nacos认证,需要通知账号和密码进行注册,以及拉取配置。

Authorization

四.Sentienl限流

1.Sentinel和Hystrix

1.1.限流和熔断

限流 , 限制流量,这里的流量我们可以理解成请求数量,其实就是限制服务器的请求并发数量,为什么要这么做?如果不做限流,那么在大量并发请求下我们的服务器会慢慢的变慢然后顶不住压力而挂掉(类似堵车)。并不是说并发越大越好,有的时候我们的项目规模和业务决定了我们不需要那么大的并发性,当大量的并发请求访问到服务器时我们需要把部分请求拒绝在外,这个是流量限制 - 限流。

熔断机制在在《Spring Cloud 极简入门》中有详细的解释,熔断机制是对服务调用链路的保护机制,如果链路上的某个服务不可访问,调用超时,发生异常等,服务会进行发熔断,触发降级返回托底数据。简单理解就是当服务器不可访问,可以返回一些预先准备好的兜底数据给用户,比如友好的提示信息,不至于直接向客户抛出异常。

1.2.Hystrix的熔断和资源隔离

其实在《Spring Cloud 极简入门》中我们已经学习过Hystrix的熔断和资源隔离机制,它的资源隔离可以通过线程池隔离和信号量隔离两种方式来实现对流量的控制。Hystrix相比Sentinel来说它的线程池隔离(限流)会造成线程上下切换对资源的消耗比较大;Hystrix使用的信号量进行资源的隔离效果不错,但是无法对慢调用进行自动降级。

1.3.Sentinel介绍

Sentinel诞生于阿里巴巴,其主要目标是流量控制和服务熔断,2018年,Sentinel演变为一个开源项目现如今成为了Spring Cloud Alibaba的一个子项目。Sentinel是通过限制并发线程的数量来减少不稳定资源的影响,而不是使用线程池,省去了线程切换的性能开销。

当资源的响应时间变长时,线程将开始被占用。当线程数累积到一定数量时,新的传入请求将被拒绝。反之亦然,当资源恢复并变得稳定时,占用的线程也将被释放,新请求将被接受。

除了限制并发性外,Sentinel可以根据响应时间降级不稳定资源也是保证可靠性的有效方法。当资源的响应时间太大时,将在指定的时间窗口中拒绝所有对该资源的访问。-- 熔断机制

此外,Sentinel支持的熔断降级维度更多,可对多种指标进行流控、熔断,且提供了实时监控和控制面板,功能更为强大。

2.Sentinel限流实战(重要)

2.1.Sentinel Server服务端

Sentinel 提供了现成的服务端供我们使用,点我下载地址,下载之后通过命令行启动

java -jar -Dserver.port=1111 sentinel-dashboard-1.6.0.jar

访问:http://127.0.0.1:1111 进入控制台,使用 sentinel/sentinel登录。 

注意:只有1.6.0及以上版本才有这个登录页面。默认用户名和密码都是sentinel。对于用户登录的相关配置可以在启动命令中增加下面的参数来进行配置:

  • -Dsentinel.dashboard.auth.username=sentinel: 用于指定控制台的登录用户名为 sentinel;

  • -Dsentinel.dashboard.auth.password=123456: 用于指定控制台的登录密码为 123456;如果省略这两个参数,默认用户和密码均为 sentinel

  • -Dserver.servlet.session.timeout=7200: 用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟;

  • -Dserver.port=1111:配置端口

主页面效果 

2.2.Sentinel 客户端接入
1.导入依赖

修改用户服务 springcloudalibaba-user-server-1010 ,加入sentinel依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2.配置Sentinel

修改yml配置,添加senticel服务控制台地址

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:1111
3.资源限流

Sentinel为我们提供了 @SentinelResource 注解标记需要限流的资源。 修改UserController,代码如下:

    @GetMapping("/user/{id}")
    //限流降级
    @SentinelResource(value="user",blockHandler="exceptionHandler")
    public User getById(@PathVariable Long id){
        System.out.println(notify);
​
        return new User(id,"zs:"+id, "我是zs");
    }
      // 限流与阻塞处理 : 参数要和 被降级的方法参数一样
    public User exceptionHandler(@PathVariable Long id, BlockException ex) {
        ex.printStackTrace();
        System.out.println("限流了...");
        return new User(-1L,"限流了","限流了");
    }

提示:这里通过@SentinelResource的value属性为资源取名为 “user” ,后续我们可以根据该资源名来进行限流。

同时这里通过 blockHandler 属性我配置了一个限流降级方法,即当“user”资源触发限流了会调用blockHandler指向的降级方法返回拖地数据,不至于抛出默认的限流异常信息给客户端(一串英文用户也看不懂) ,需要注意的是:降级方法要和被限流的方法参数一致,然后加上 BlockException异常对象。

当然,也可以通过 blockHandlerClass 属性把降级方法写在一个专门的类中,如:

@SentinelResource(value="user",blockHandler="exceptionHandler"
,blockHandlerClass=ExceptionUtil.Class)

降级类

public final class ExceptionUtil {
    public static User exceptionHandler(Long id ,lockException ex) {
       //...
    }
}
2.3.Sentinel设置限流策略

启动应用 springcloudalibaba-user-server-1010 ,然后通过浏览器访问 http://localhost:1010/user/11 ,然后登录Sentinel控制台,在“实时监控”列表中可以看到资源的相关监控信息的 

在 “族点链路” 列表中可以看到资源的调用链 ,并且可以通过“流控”按钮设置流控规则 也可以在“流量控制”菜单中我们可以针对资源进行限流规则的设置。如下: 这里我添加了一个流控规则,资源名对应客户端 @SentinelResource(value="user".. 注解的资源,通过QPS限流(每秒请求数量),阈值是 1 ,意思是“user”这个资源每秒只能有1个请求进来,多余的请求会触发限流,返回降级数据。

2.4.限流测试

通过浏览器频发访问 “user”资源,当QPS大于1就会触发限流,效果如下: 

3.Sentinel流控模式(了解)

3.1.直接

Sentinel默认的流控处理就是【直接->快速失败】,QPS达到阈值,当前资源直接失败。在流控规则中配置如下: 

3.2.关联

关联的资源达到某个阈值,限流自己,如:限流的资源是/user/delete ,关联的资源是/user/list,当/user/list达到阈值,限流user/delete , 举例: 支付并发太高,可以限制下单的流量

3.3.链路

限流线路调用链路的入口,如 /user/list 资源中 调用了 /dept/list ,对/dept/list添加限流,当/dept/list达到阈值,其实限流的是/user/list,因为他是访问的入口

4.Sentinel流控效果(了解)

4.1.快速失败

快速失败:(RuleConstant.CONTROL_BEHAVIOR_DEFAULT)是默认的流控方式,当流量达到阀值直接返回异常,QPS达到任何规则阈值后,后续请求就会立即拒绝,并抛出FlowException 异常。简单理解:并发太高,直接请求拒绝

4.2.Warm Up预热

Warm Up预热:(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,根据codeFactor(默认3)的值,从(阀值/codeFactor)为初始阀值,经过预热时长,才到达设置的QPS的阀值,即预热/冷启动方式。简单理解:慢慢的增大处理并发的能力提示:初始的QPS阈值为 100 / 3 =33 ,10秒后 QPS阈值达到 100.

当系统长期并发不高,流量突然增加可能会直接把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值的上限,给系统一个预热的时间,避免冷系统被压垮。

4.3.排队等待

排队等(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER),忽然增加的请求并发量达到了限流阈值后续请求会被决绝,有时候我们可能更希望后续的请求可以加入队列进行排队,慢慢执行,而不是直接拒绝请求,这种方式后严格控制请求通过的时间间隔,也即是让请求以均匀的速度通过,对应的是漏桶算法,这种方式主要用于处理间隔性突发的流量,例如消息队列。 简单理解:突发流量处理不过来,让请求排队。提示:QPS阈值为100,超过的请求会排队,排队超时时间为 10S

5.热点限流(扩展)

还有一种特殊的动态限流规则,用于限制动态的热点资源 , 比如对同一个用户的请求频率做限定,比如对参数进行限定,比如对参数的值做限定(比如对商品ID为1的资源做限流)。

5.1.参数限流

参数限流就是 对资源的参数进行限流,我们来编写一个方法,接受两个参数:p1,和p2并设置好限流降级。

//限流降级
@SentinelResource(value="/parameterLimit",blockHandler="parameterLimitHandler")
@GetMapping(value="/parameterLimit")
public String parameterLimit(@RequestParam("p1") String p1 ,@RequestParam("p2") String p2){
    return "parameterLimit方法调用成功...";
}
// 限流与阻塞处理
public String parameterLimitHandler(@RequestParam("p1") String p1 ,@RequestParam("p2") String p2,BlockException ex) {
    return "限流了...";
}

配置热点规则 , 对第一个参数限流 , 当第一个参数超过了1的QPS就熔断降级。

5.2.参数值限流

对某一个参数的值满足某种条件的时候就进行限流,如下配置

意思是第一个参数的值为 haha 的时候限流阈值为10 , 超过 QPS > 10的并发就限流。

举例:应用场景比如说商品名称为“华为p40”的商品并发特别高,我们可以针对参数商品名为“华为p40”的商品进行限流。

6.系统规则(扩展)

6.1.配置全局限流规则

系统规则可以看做是总的限流策略,所有的只要都要受到系统规则的限制。上面的意思是最大并发只能允许 10 个线程数,并且是作用于全局的。

7.Gateway使用Sentinel限流(重要)

Spring Cloud Gateway 作为微服务的网关,它是微服务的访问入口,当请求的流量洪峰到来我们可以在Gateway网关层通过Sentinel对请求进行流控,把好第一道关。

7.1.导入依赖

这里我们需要导入sentinel基础依赖和 sentinel-gateway 整合依赖

<!--    限流和gataway使用-->
<dependency>
   <groupId>com.alibaba.cloud</groupId>
   <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
 </dependency>
 <dependency>   
   <groupId>com.alibaba.cloud</groupId>
   <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
 </dependency>
7.2.配置Sentinel地址

修改yml配置,增加Sentinel服务地址

spring:
    cloud:
      sentinel:
          transport:
            dashboard: localhost:1111
7.3.配置限流规则

启动Gateway,登录sentinel控制台,对url资源进行流控限制,配置方式和前面的配置方式一样,童鞋们可以自己测试一下。

7.4.限流降级
@Configuration
public class SentinelConfig {
    public SentinelConfig(){
        GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                return ServerResponse.ok().body(Mono.just("限流啦,请求太频繁"),String.class);
            }
        });
    }
}

8.Nacos存储限流规则

在前两章节我们学习了通过Sentinel的限流和熔断机制来保护微服务,提高系统的可用性,但是有一个问题,我们在Sentinel配置了限流,熔断策略,默认情况下Sentinel的数据是基于内存存储,当客户端断开,或者Sentinel重启数据就会丢失,这不是我们愿意看到的。所有我们需要的Sentinel做数据持久。 Sentinel 中支持5种持久化的方式:file、redis、nacos、zk和apollo,本片文章针对于Nacos进行持久化配置。

8.1.整合Nacos持久化限流规则

第一步:导入基础依赖,springcloudalibaba-user-server-1010为例子,修改pom增加Sentinel和Nacos持久化配置依赖 sentinel-datasource-nacos ,如下:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    <!--Sentinel和Nacos做持久的-->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-nacos</artifactId>
        <version>1.5.2</version>
     </dependency>
</dependencies>

第二步:配置持久化nacos地址

spring:
  application:
    name: user-server
  cloud:
    nacos:
      config: #配置中心
        server-addr: localhost:8848
        file-extension: yaml
        prefix: application-user
    sentinel:   #限流服务器sentinel配置
      transport:
        dashboard: localhost:1111
#====================持久化配置=================================        
      datasource:
        flow:
          nacos: #限流持久配置
            server-addr: localhost:8848 #使用nacos的持久
            dataId: application-user-dev    #获取限流的数据源的dataId
            groupId: DEFAULT_GROUP
            rule-type: flow #类型:限流
#=====================================================            
  profiles:
    active: dev
​

这里其实是在之前的配置基础上增加了 spring.cloud.sentinel.datasource持久化数据源的配置,对应了NacosDataSourceProperties 配置类具体含义如下:

  • spring.cloud.sentinel.datasource.ds.nacos.server-addr:nacos的访问地址

  • spring.cloud.sentinel.datasource.ds.nacos.groupId:nacos中存储规则的groupId

  • spring.cloud.sentinel.datasource.ds.nacos.dataId:nacos中存储规则的dataId

  • spring.cloud.sentinel.datasource.ds.nacos.rule-type:该参数是用来定义存储的规则类型。所有的规则类型可查看枚举类:...datasource.RuleType,每种规则的定义格式可以通过各枚举值中定义的规则对象来查看,比如限流规则可查看:...flow.FlowRule

简而言之,这里是配置了Sentinel持久化针对于Nacos的相关信息,程序会去地址为localhost:8848的Nacos中查找DataId为 application-user-sentinel-dev,GourpId为 DEFAULT_GROUP的文件作为限流策略(rule-type: flow代表限流)。

第三步:编写测试用的Controller这个controller我们待会用来做限流测试,

@RestController
   public class TempController {
​
      @GetMapping("/hello")
      public String hello() {
          return "测试数据";
      }
  }
8.2.Nacos持久化Sentinel限流规则

第一步:在配置列表增加配置如下:

[
    {
        "resource": "/hello",
        "limitApp": "default",
        "grade": 1,
        "count": 10,
        "strategy": 0,
        "controlBehavior": 0,
        "clusterMode": false
    }
]

这里做一个解释

  • resource:对那个资源进行限流

  • limitApp:这个是流控的调用者,default 代表不区分调用者

  • grade:限流方式0是根据并发数量限流,1是表根据QPS来限流

  • count:限流阈值,达到这个阈值就被限流,触发降级。

  • strategy:基于调用链的流控制策略。0 直接,1 关联 2 链路

  • controlBehavior:流控效果,0 直接拒绝,1是Warm Up,2是匀速排队

  • clusterMode:是否为集群

上面的配置项目对应了 com.alibaba.csp.sentinel.slots.block.flow.FlowRule 限流规则类。程序启动,Sentinel通过 NacosDataSource 从Nacos中查找配置。具体效果如:

注意:这里的DataId 和 Group其实是和上一步 yml配置中的DataId和Group相对应,这里配置的是一个数组,意思是可以配置多个限流策略

第二步:启动测试 ,启动springcloudalibaba-user-server-1010 ,向 /hello 资源发起访问,然后观察Sentinel控制台流控规则是否有了一条限流策略。

这里我们看到,我们并没有在Sentinel设置流控规则,而是通过Nacos配置的流控规则,在客户端对Sentinel做Nacos持久配置,那么Sentinal自动会去同步Nacos中的流控规则,同时同步到客户端本地,只要Nacos是做了持久化的,流控规则就不会丢失。

8.3.Nacos持久化Sentinel降级规则

第一步:在Nacos配置列表增加文件 如:application-user-degrade-dev ,内容如下

[
    {
        "resource": "GetUserByID",
        "grade": 0,
        "count": 10,
        "timeWindow": 5
    }
]

解释一下

  • resources : 资源名

  • grade : 慢调用比例 0 ;异常比例 1 ;异常数 2;

  • count : 最大RT,最大平均响应时间

  • timeWindow :时间窗口,即熔断时长

效果如:

第二步:项目中增加配置

spring:
  application:
    name: service-user
  cloud:
    sentinel:
      datasource:
        flow: #限流的配置
          nacos: #限流持久配置
            server-addr: 127.0.0.1:8848 #使用nacos的持久
            dataId: application-user-sentinal-dev   #获取限流的数据源的dataId
            groupId: DEFAULT_GROUP
            rule-type: flow #类型:限流
##==================================================================            
        degrade: #降级的配置
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: application-user-degrade-dev
            groupId: DEFAULT_GROUP
            rule-type: degrade

第三步:启动测试,观察sentinel的熔断规则列表

五.Sentinel熔断

1.概述

1.1.什么是熔断

在上一章节我们探讨了Sentinel的流控(限流)功能,Sentinel除了流控还提供了服务熔断和降级机制,服务之间的调用关系错综复杂,微服务的调用链上的某些服务资源不稳定(宕机,异常,超时)可能会导致可能请求的失败和请求的堆积,调用链产生连锁反应可能会导致整个微服务架构瘫痪。服务熔断降级机制是保障高可用的重要措施之一。

1.2.Sentinel熔断

Sentinel的服务熔断机制会对调用链上的某个不稳定(宕机,异常,超时)的资源,做出请求限制,快速失败,避免影响到其它的服务而导致级联错误。资源熔断后,在后续的一定时间(时间窗口)之内,对该服务的请求都自动熔断,抛出 DegradeException异常。

Sentinel拥有比Hystrix更强大和丰富的功能,能满足我们的各种应用场景,并且经历过淘宝双十一的考验,是微服务架构中熔断机制的不二选择。

2.Sentnel熔断实战(重要)

2.1.资源熔断降级

修改springcloudalibaba-user-1010工程,修改UserController ,通过@SentinelResource注解的fallback 属性指定降级方法。

    // 限流降级
    public User exceptionHandler(@PathVariable Long id, BlockException ex) {
        ex.printStackTrace();
        System.out.println("限流了...");
        return new User(-1L,"限流了","限流了");
    }
    // 熔断降级,参数和返回值与源方法一致
   public User getByIdfallback(@PathVariable Long id){
        System.out.println(notify);
        return new User(id,"zs:"+id, "熔断托底了");
    }
    
    @GetMapping("/user/{id}")
    //限流降级
    @SentinelResource(value="user",blockHandler="exceptionHandler",fallback = "getByIdfallback")
    public User getById(@PathVariable Long id){
        int i = 1 / 0;  //方法异常,触发熔断
        return new User(id,"zs:"+id, "我是zs");
    }
​

提示:方法中通过 int i = 1 / 0; 模拟异常,然后会熔断触发降级调用降级方法 。 通过 fallback 属性指定熔断的降级方法 ,熔断方法参数也要和被熔断方法参数一致。

注意:这里可以通过 @SentinelResource注解的 exceptionsToTrace 属性忽略异常,即针对某个异常不熔断。

2.2.配置降级策略

在Sentinel控制台,在族点链路菜单中找到“user”资源,然后点击“降级”按钮添加降级策略,如下:这里的降级策略为“RT”,大概意思是:如果并发数大于5 (QPS > 5) ,然后平均响应时间大于200毫秒,那么接下来的2秒钟之内对该资源的请求会被熔断降级。

2.3.测试熔断

启动springcloudalibaba-user-1010工程,访问 http://localhost:1010/user/2 ,浏览器返回:这里已经返回了托底数据,其实是因为“user”资源方法中抛出了异常,触发了熔断降级。

3.降级策略(了解)

资源在什么情况下会触发熔断降级?调用异常,达到流控,调用超时 都会触发熔断降级,在上面的案例中我们看到资源的降级策略有 RT,异常比例,异常数三种方式,我们可以通过这三种方式来定义资源是否稳定,决定是否要进行熔断降级。

3.1.平均响应RT

平均响应时间 (DEGRADE_GRADE_RT):当资源的平均响应时间超过阈值(DegradeRule 中的 count,以 ms 为单位)之后,资源进入准降级状态。如果接下来 1s 内持续进入 5 个请求(即 QPS >= 5),它们的 RT 都持续超过这个阈值,那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置。

是不是很生涩难懂?我们根据下面这个配置来理解:我们挑关键信息来理解上面那句话这里配置的RT是200意思是对资源的多次请求平均响应时间都超过200毫秒,意思是 1s 内持续进入 5 个请求(即 QPS >= 5),这五个请求的平均响应时间都超过了200,后续的2秒之内(时间窗口)请求这个方法都被熔断,触发降级

总结一下:RT其实就是平均相应时间太长资源熔断。

3.2.异常比例

异常比例(DEGRADE_GRADE_EXCEPTION_RATIO):每秒请求量 > 5 ,当资源的每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。

根据下面这个配置来理解上面配置的意思就是“user”这个资源的异常比例超过了0.2,即10个请求有两个都异常了,资源被熔断,在接下来的2秒钟之后请求这个方法都被熔断,触发降级。

总结一下:异常比例就是按照资源的请求失败率来熔断。

3.3.异常数

异常数 (DEGRADE_GRADE_EXCEPTION_COUNT):当资源近 1 分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。

根据下面这个配置来理解这里的意思是一分钟(61s)超过5个异常请求,服务进行熔断。后续请求都拒绝。

注意:异常降级仅针对业务异常,对 Sentinel 限流降级本身的异常(BlockException)不生效

总结一下:异常数就是按照 一分钟的异常的数量 来熔断。

4.Feign整合Sentinel熔断(重要)

Spring Cloud Alibaba是Spring Cloud的一个子项目,OpenFeign是Spring Cloud的客户端负载均衡器,使用Spring Cloud Alibaba依然可以很方便的集成OpenFeign,如果要使用OpenFeign作为服务客户端负载均衡,那么我们需要考虑OpenFeign开启Sentinel进行服务熔断降级。

4.1.开启Sentinel

OpenFeign与Sentinel组件集成除了引入sentinel-starter依赖关系之外,还需要在属性文件中启用Sentinel支持:feign.sentinel.enabled=true

feign:
  sentinel:
    enabled: true #熔断
4.2.给Feign接口降级

这里跟Feign开启Hystrix降级一样,还是可以使用fallback属性

@FeignClient(value = "user-server",fallbackFactory = UserClientFallback.class)
public interface UserClient {
​
    @GetMapping("/user/{id}")
    User getById(@PathVariable Long id);
}
4.3.编写降级类
@Component
public class UserClientFallback implements UserClient {    
    @Override    
    public User getById(Long id) {        
        return new User(-1L,"无此用户","无此用户");    
    }
}

到这里我们已经完成了Feign和Sentinel的兼容使用,是不是很简单呢,因为它的集成方式和Hystrix简直一模一样

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值