Spring Cloud alibaba

1.引言

目前Spring Cloud进入了维护模式,而Spring Cloud alibaba对Spring Cloud做了封装,使用起来更简单。包含的功能有服务限流降级、服务注册于发现、分布式配置管理、消息驱动能力、阿里云对象存储、分布式任务调度等。

参考文档:

https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html

源代码:https://github.com/zhongyushi-git/spring-cloud-alibaba-demo.git

2.Nacos

一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。是注册中心与配置中心的组合。官网:https://nacos.io/zh-cn/index.html

2.1下载

打开https://github.com/alibaba/nacos/releases下载需要的版本,这里以1.1.4版本为例说明。

2.2安装

2.2.1在windows系统安装

下载压缩包后解压即可使用。进入bin目录,双击startup.cmd看到下图说明运行成功。

默认是以集群方式启动,若启动报错,那么需要修改为单机版启动,在bin目录打开cmd,输入下面的命令进行启动。

startup.cmd -m standalone

访问http://localhost:8848/nacos,登录用户名和密码都是nacos。登录之后的页面如下,可以看到相关想信息。

2.2.2在Linux系统安装

把下载好的压缩上传制到Linux后解压

tar -zxvf nacos-server-1.1.4.tar.gz -C /usr/local

解压之后单机版启动,启动之后在浏览器访问nacos首页,同上。

bash startup.sh -m standalone

2.3基础环境搭建

创建maven的父工程spring-cloud-alibaba-demo,删除src目录。导入依赖,进行版本锁定

    <!--统一管理jar包版本-->
    <properties>
        <spring.boot.version>2.2.2.RELEASE</spring.boot.version>
        <spring.cloud.alibaba.version>2.2.0.RELEASE</spring.cloud.alibaba.version>
        <spring.cloud.version>Hoxton.SR1</spring.cloud.version>
    </properties>

    <!--  依赖管理,父工程锁定版本-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring.cloud.alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

2.4服务注册

1)创建服务提供者子模块cloud-alibaba-provider8001,导入依赖

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--springcloud alibaba nacos-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>

2)application.yml配置

server:
  port: 8001

spring:
  application:
    name: cloud-alibaba-nacos-provider
  cloud:
    #配置nacos地址
    nacos:
      #服务器地址
      server-addr: 127.0.0.1:8848
      #服务注册与发现地址
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}

#开启端口暴露
management:
  endpoints:
    web:
      exposure:
        include: "*"

3)创建启动类

package com.zys.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class NacosProviderMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(NacosProviderMain8001.class,args);
    }
}

4)创建controller接口

package com.zys.cloud.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Value("${server.port}")
    private String port;

    @GetMapping("/user/get")
    public String get() {
        return "provider port is :" + port;
    }
}

5)启动服务提供者,在nacos页面的服务列表中可以看到服务已注册进来。那么此时服务的注册就已完成,非常简单。

6)同理,按照cloud-alibaba-provider8001方式创建服务提供者子模块cloud-alibaba-provider8002,端口为8002。启动后发现nacos中服务的集群数目变成了2。

2.5服务调用

nacos并不提供服务调用的方法,因此还需要使用SpringCloud的方式进行调用,这里使用OpenFeign进行说明(关于OpenFeign的用法其他文章已介绍)。

1)创建服务消费者子模块cloud-alibaba-consumer80,导入依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--springcloud alibaba nacos-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>

2)application.yml配置

server:
  port: 80

spring:
  application:
    name: cloud-alibaba-nacos-consumer
  cloud:
    #配置nacos地址
    nacos:
      #服务器地址
      server-addr: 127.0.0.1:8848
      #服务注册与发现地址
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}


feign:
  client:
    config:
      #指定全局
      default:
        #连接超时时间
        connectTimeout: 5000
        #服务等待时间
        readTimeout: 5000
        loggerLevel: full

logging:
  level:
    com.zys.cloud.client.UserClient: debug

虽然是调用别的服务,但也需要把自身服务注册到nacos.

3)创建启动类

package com.zys.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ConsumerMain80 {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerMain80.class, args);
    }
}

4)创建Client接口,用于接口映射

package com.zys.cloud.client;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient(value = "cloud-alibaba-nacos-provider")
public interface UserClient {

    @GetMapping("/user/get")
    String get();
}

5)创建controller接口

package com.zys.cloud.controller;

import com.zys.cloud.client.UserClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/consumer")
public class UserController {

    @Autowired
    private UserClient userClient;

    @GetMapping("/get")
    public String get() {
        return userClient.get();
    }
}

6)启动服务,可以在nacos页面的服务列表中看到两个注册的服务。

访问http://localhost/consumer/get,看到是8001和8002进行轮询负载的。是因为nacos默认支持负载均衡,原因是它默认引入了ribbon。

2.6服务配置

2.6.1基本配置

为了不改动上述的代码,这里新建一个模块说明服务的配置,原理是一样的。

1)创建配置的客户端子模块cloud-alibaba-config-client,导入依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--springcloud alibaba nacos-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
    </dependencies>

这里同时引入了服务注册和服务配置的依赖。作为客户端,当然需要注册到nacos,而配置又是此服务必不可少的。

2)yml配置

bootstrap.yml:系统级别的配置,主要配置配置中心的相关信息。

spring:
  cloud:
    nacos:
      #服务器地址
      server-addr: 127.0.0.1:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}
      config:
        #配置中心地址
        server-addr: ${spring.cloud.nacos.server-addr}
        #指定配置的格式,有yaml和properties两种
        file-extension: yaml

application.yml:主要配置服务的名称及激活的配置文件

spring:
  application:
    name: nacos-config-client
  profiles:
    active: dev

3)创建启动类

package com.zys.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class NacosConfigClientMain {
    public static void main(String[] args) {
        SpringApplication.run(NacosConfigClientMain.class,args);
    }
}

4)创建controller接口

package com.zys.cloud.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
//动态刷新
@RefreshScope
public class UserController {

    @Value("${config.info}")
    private String info;

    @GetMapping("/config/get")
    public String get() {
        return "The config info is :" + info;
    }
}

需要注意的是,这里在类上加了@RefreshScope注解,用于自动刷新。若不添加,则无法进行自动的配置刷新。

5)创建统一的配置文件

在创建之前,先了解一些dataID的命名规则,它的完整格式为${prefix}-${spring.profile.active}.${file-extension}。

prefix :默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置。
spring.profile.active :即为当前环境对应的 profile。
file-exetension: 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 和 yaml 类型。

假如spring.application.name=nacos-config-client,环境为dev,后缀名是yaml,那么dataID就是nacos-config-client-dev.yaml。这里不存在主/从配置文件的说法,只指定不同环境的配置,公共的配置都放在自己的环境中。另外,dataId后缀必须是yaml或properties。

了解之后,就在nacos的配置管理页面新建一个配置文件,然后发布。

配置代码:

server:
    port: 3344

config:
    info: '我的名字叫张三'

 6)测试

启动3344,访问http://localhost:3344/config/get,可以看到配置的信息。然后修改配置中的config.info内容,再刷新页面,发现配置信息也更新了。此时就做到了配置实时刷新。

2.6.2分类配置

级别大小:namespace > Group > dataId。

1)dataId方案

一个dateId就是一个配置文件。在nacos页面再创建一个配置文件,作为测试环境配置

修改application.yml的环境为test。

重启后访问http://localhost:3355/config/get,可以看到test环境的配置信息。

2)Group方案

在上述的章节中,并没有去指定Group,而是采用的默认的名称DEFAULT_GROUP,如果需要自定义分组名称,则在创建配置时指定分组名即可,不过需要在bootstrap.yml在指定组名。

新建一个配置文件,分组名为GROUP_TEST

修改application.yml的环境为info,然后在bootstrap.yml指定组名

重启后访问http://localhost:3344/config/get,可以看到info环境的配置信息。

3)namespace方案

用于区分不同的部署环境,实现隔离。命名空间是最大的,需要设置的话就创建命名空间(id一般不指定,自动生成即可),在配置文件中指定创建的命名空间的id即可。

2.7持久化配置

nacos默认自带的是嵌入式数据库derby,持久化就需要切换到MySQL,MySQL版本5.7以上。

1)执行sql脚本

在下载的nacos文件夹中,nacos-server-1.1.4\nacos\conf\nacos-mysql.sql即是sql脚本,先创建一个名为nacos的数据库,然后执行这个脚本即可。

2)修改配置文件

打开nacos-server-1.1.4\nacos\conf\application.properties,在最后添加

#增加支持mysql数据源配置
spring.datasource.platform=mysql

db.num=1
db.url.0=jdbc:mysql://localhost:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=123456

3)启动测试

重启nacos,发现之前配置的信息没有了,原因是MySQL中并没有进行配置。这时在nacos页面创建一个名为nacos-config-client-info.yaml的配置文件如下:

启动服务配置客户端,访问http://localhost:3344/config/get,可以看到info环境的配置信息。其配置信息在表config_info中可看到。

2.8集群配置

在搭建集群之前,默认在Linux已安装完成nocas。另外,nginx单机版也在Linux搭建完成,用于负载均衡nacos服务,MySQL在Linux已安装完成(MySQL版本5.7+)。

1)执行sql脚本(同上一小节)

2)配置nacos数据源,修改application.properties文件,在最后添加

#增加支持mysql数据源配置
spring.datasource.platform=mysql

db.num=1
db.url.0=jdbc:mysql://localhost:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=123456

3)获取本机的ip

hostname -i

4)配置cluster.conf

打开文件

cp cluster.conf.example cluster.conf
vim cluster.conf

把内容修改如下:

172.16.68.248:8849
172.16.68.248:8850
172.16.68.248:8851

需要注意的是,这里的ip必须是上一步获取的本机ip。

5)修改startup.sh启动文件

vim startup.sh

修改的文件前后对比,主要添加了启动的端口号

 

   

 6)启动集群

./startup.sh -p 8849
./startup.sh -p 8850
./startup.sh -p 8851

在启动的时候,遇到了一个大坑,就是安装的jdk必须手动配置java_home,否则会报错。

3.Sentinel

学习地址:https://github.com/alibaba/Sentinel/wiki/介绍

Sentinel主要从流量控制、熔断降级、系统负载保护维度保护服务的稳定性。

3.1下载与安装

1)下载地址https://github.com/alibaba/Sentinel/releases,选择对应的版本下载即可。这里以1.8.2版本为例

可以下载压缩包,也可以直接下载jar。本章节在Windows中说明,就直接下载jar进行说明。

2)下载到本地后,在其目录下打开cmd,输入命令

java -jar sentinel-dashboard-1.7.2.jar

3)在浏览器访问http://localhost:8080,看到下面的页面说明安装成功。

用户名和密码都是sentinel。

4)登录后看到仪表盘是空的,因为现在没有监控任何的服务。

3.2初始化监控

为了不改动上述的代码,这里新建一个模块进行说明,原理是一样的。

1)创建一个模块cloud-alibaba-sentinel,导入依赖

      <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--springcloud alibaba nacos-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--springcloud alibaba sentinel-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

2)配置application.yml,简单起见,配置文件在本地进行配置

server:
  port: 8401
spring:
  application:
    name: cloud-alibaba-sentinel-service
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848
      discovery:
        server-addr: ${spring.cloud.nacos.server-addr}
    sentinel:
      transport:
        # sentinel dashboard的地址
        dashboard: 127.0.0.1:8080
        # sentinel dashboard内部通信端口,默认为8719,如果被占用会自动+1,直到找到为止
        port: 8719

management:
  endpoints:
    web:
      exposure:
        include: "*"

3)创建启动类

package com.zys.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class SentinelMain {
    public static void main(String[] args) {
        SpringApplication.run(SentinelMain.class, args);
    }
}

4)创建controller

package com.zys.cloud.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FlowLimitController {

    @GetMapping("/testA")
    public String testA(){
        return "--------testA";
    }

    @GetMapping("/testB")
    public String testB(){
        return "--------testB";
    }


}

5)测试。先启动nacos服务,再启动sentinel服务,再启动8401。访问http://localhost:8401/testA后会在仪表盘看到生成了一个服务:

将接口testA多调用几次,再看仪表盘

其中QBS表示1秒的请求数,QPS表示1秒的拒绝请求数。

原理:只要服务加入了Sentienl并进行了配置,那么在调用服务时,就会通过内部通信服务把日志信息发送给dashboard服务,其在页面上展示。因此只有的服务调用时dashboard才会进行初始化。

6)簇点链路

打开簇点链路的菜单,可以看到链路的信息,可操作的按钮包含流控、熔断、热点和授权,后续一一介绍。

3.2流控

流控:流量控制(flow control),其原理是监控应用流量的QPS或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。

3.2.1阈值类型-QPS

QPS表示每秒的请求数。可在簇点链路中选择链路的点击流控按钮添加,也可在流控规则中添加。其他的功能类似。这里以/testA的流控为例:

上图的配置,也就是说对于请求/testA,当每秒请求的次数超过阈值,那么会直接返回失败的信息。保存后显示列表如下:

访问localhost:8401/testA结果是正常的,若快速的刷新几次,会发现返回了流控的信息:

对于针对来源,默认使用default,那么也可以指定来源,那么当指定的这个来源调用/testA请求时会进行流控,其他服务调用/testA时不进行流控,也就是对来源进行针对性的流控。

3.3.2阈值类型-并发线程数

当然也可设置并发线程的阈值,当某一时刻并发线程数量超过时会进行流控。

1)点击编辑,将/testA的阈值类型修改并发线程数

2)使用Jmeter对/testA发送超过阈值的并发请求,那么在发送的同时再访问/testA就会出现流控。

3.3.3 流控模式-关联

1)说明:前面的两种的流程模式都设置为直接,这种模式是默认的,也就是说流量控制规则到达阈值时直接触发流量控制。本小节说明关联模式,均以QPS类型说明,后同。

2)关联:当两个资源之间具有资源争抢或者依赖关系的时候,这两个资源便具有了关联。比如对数据库同一个字段的读操作和写操作存在争抢,读的速度过高会影响写得速度,写的速度过高会影响读的速度。如果放任读写操作争抢资源,则争抢本身带来的开销会降低整体的吞吐量。关联的关系是反向关联。

3)上述代码中的/testA和/testB就是关联关系,它们在同一个controller中,占用相同的资源,编辑配置如下:

使用Jmeter对/testB发送超过阈值的并发请求,那么在发送的同时再访问/testA就会出现流控。原因是两个请求相互争抢资源,进行了流控。

3.3.3 流控模式-链路

链路模式也就是对某一条链路进行流控。如用户服务会调用订单服务,商品服务也会调用订单服务,就存在两条链路。在某个时刻,对商品服务->订单服务这条链路进行流控,从而保证订单服务的正常使用,最终让用户服务可以正常调用订单服务,虽然限流了商品服务这条链路,但不影响用户服务这条链路。

3.3.4流控效果-快速失败

默认的流量控制方式,当QPS超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException 。前面已经使用过多次。

3.3.5流控效果-Warm Up

预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。它有一个冷加载因子,值是3。曲线图如下:

新加/testA的流控规则如下:

当1秒同时有20个请求,预热时间是10秒。那么服务会先处理7个请求(20/3),后面依次处理,当达到20秒时处理完所有的请求。

3.3.6流控效果-排队等待

让请求以均匀的速度通过。修改/testA的规则:

也就是说,当有大量的请求来时,每秒只处理20个请求,其他的请求进行排队等待,依次类推。当后面排队的时间超过5秒时就报错,显示流控信息。

3.3熔断降级

一个服务常常会调用别的模块,如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。而Sentinel在服务出现不稳定情况时,会对其进行限制,请求快速失败,避免影响到其他资源而导致级联错误。当资源被降级后,在接下来的时间窗口内,对该资源的调用都自动熔断。

3.3.1降级策略

(1)慢调用比例:当单位统计时长内请求数目大于设置的最小请求数目,并且平均响应时间超过最大RT的请求的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。

经过熔断时长后熔断器会进入探测恢复状态,若接下来的一个请求成功完成则结束熔断,否则会再次被熔断。

说明:在1000ms内请求数超过5个,且平均响应时间超过300ms的请求的比例(超过300ms的请求占总请求的比例)大于0.4,则该资源自动熔断10s。10s后根据下一个请求判断是否再次被熔断。

(2)异常比例:当单位统计时长内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。

经过熔断时长后熔断器会进入探测恢复状态,若接下来的一个请求成功完成则结束熔断,否则会再次被熔断。

说明:在1000ms内请求数超过5个,且异常的比例(异常的请求占总请求的比例)大于0.8,则该资源自动熔断15s。15s后根据下一个请求判断是否再次被熔断。

(3)异常数:当单位统计时长内的异常数目超过阈值之后会自动进行熔断。

经过熔断时长后熔断器会进入探测恢复状态,若接下来的一个请求成功完成则结束熔断,否则会再次被熔断。

说明:在1000ms内请求数超过5个,且异常的请求超过6个,那么该资源将自动熔断20s。20s后根据下一个请求判断是否再次被熔断。

3.3.2注解@SentinelResource的使用

前面的所讲的流控或降级,其返回的数据都是 Blocked by Sentinel (flow limiting) ,当然可以自定义。@SentinelResource和@HystrixCommand的作用是类似的,都是来指定流控或降级时返回的信息。

在方法上加@SentinelResource注解,且使用blockHandler(或者blockHandlerClass)指定流控或降级时的自定义提示,而blockHandler函数访问范围需要是public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数(类型是BlockException),且和原方法在同一个类中。使用fallback 指定未流控或降级发生异常时的自定义提示,其方法必须是public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配。

下面通过对/testC进行流控和降级来说明:

1)流控配置:

 

2)降级配置:

3)后台代码:

    @GetMapping("/testC")
    @SentinelResource(value = "aaa", blockHandler = "testCBlockHandler",fallback = "testCFallback")
    public String testC(Integer id) {
        if (id < 0) {
            throw new RuntimeException("参数值格式错误");
        }
        return "--------testC";
    }

    //自定义降级或熔断时的提示信息
    public String testCBlockHandler(Integer id, BlockException exception) {
        //判断异常的类型
        if (exception instanceof FlowException) {
            return "你被限流了,请稍后再试";
        } else if (exception instanceof DegradeException) {
            return "你被降级了,请稍后再试";
        }
        return "当前服务不可用";
    }

    //自定义未限流时发生异常的提示信息
    public String testCFallback(Integer id){
        return "参数不合法";
    }

在@SentinelResource指定了value,其值就是要流控或降级的资源名,必须配置。

当访问/testC?id=8时,快速刷新,会出现流控提示信息。

当问/testC?id=-5时,刷新1此,会出现错误提示信息。

当问/testC?id=-5时,刷新5次以上,会出现降级提示信息。

3.4规则持久化

你有没有发现,每次无论重启sentinel服务还是要监控的服务,sentinel页面的配置规则都会消失,这是因为这些规则没有持久化,对应大量的配置规则,持久化也非常重要,可将其配置到nacos中。

这里直接在cloud-alibaba-sentinel模块进行说明:

1)导入依赖

        <!--springcloud alibaba sentinel-datasource-nacos-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

2)在yml配置,已存在配置省略:

spring:
  cloud:
      # 流控规则持久化到nacos
      datasource:
        dsl:
          nacos:
            server-addr: ${spring.cloud.nacos.server-addr}
            data-id: ${spring.application.name}
            group-id: DEFAULT_GROUP
            data-type: json
            rule-type: flow

3)在nacos中添加配置文件,如下图:

 json内容:

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

可看到json中是一个数组,数组中只有一个元素,那么针对/test的请求的配置规则会存下来,不会因为重启而丢失,而其他的请求的配置规则还是丢失。针对这些请求,都按照这种规则配置在数组中即可。

4.Seata

官网:https://seata.io/zh-cn/index.html

一次业务操作需要跨多个数据源或需要跨多个系统进行远程调用,就会产生分布式事务问题。Seata是一种分布式事务的解决方案,在服务搭建正确的情况下,在业务上添加@GlobalTransactional

4.1术语(一ID+三组件模式)

1)XID:(Transaction ID)全局唯一的事务ID

1)TC:(Transaction Coordinator)事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚

2)TM:(Transaction Manager)控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议

3)RM:(Resource Manager)控制分支事务,负责分支注册、状态汇报,并接收事务协调器的指令,驱动分支(本地)事务的提交和回滚

4.2处理过程

1)TM向TC申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID

2)XID在微服务调用链路的上下文中传播

3)RM向TC注册分支事务,将其纳入XID对应全局事务的管辖

4)TM向TC发起针XID的全局提交或回滚决议

5)TC调度XID下管辖的全部分支事务完成提交或回滚请求。 

4.3下载安装

1)下载地址:https://github.com/seata/seata/releases,下载对应版本即可。

5.微服务架构整合

相比之下,使用SpringCloud+SpringCloud alibaba效果会更好。整合的组件说明如下表:

微服务组件 框架 具体组件
服务注册 SpringCloud alibaba nacos
服务调用 SpringCloud openfeign
服务配置 SpringCloud alibaba nacos
服务网关 SpringCloud gateway
服务熔断和降级 SpringCloud alibaba sentinel
服务负载均衡 SpringCloud Ribbon。默认已有

涉及到整合,那么两者的版本需要进行匹配并进行统一管理。

 

posted @ 2020-05-03 20:11  钟小嘿  阅读(2597)  评论(0编辑  收藏  举报