spring cloud alibaba - sentinel&OpenFeign使用

       

目录

一 sentinel的基本使用

一 限流规则

二 熔断规则

1 慢调用比例

2 异常比例

3 异常数

三 sentinel限流规则的其它介绍

1 热点规则

2 授权规则

3 系统规则 

二 sentinel的进阶使用

一 自定义响应信息

二 配置持久化(nacos)

三 OpenFeign使用介绍


        sentinel是一个流量治理组件,可以进行服务限流,熔断降级等系统保护。对于一些高并发高访问的服务,为了保证系统的稳定性,它是一个必不可少的组件。一般它会搭配gateway,feign等组件进行使用。与gateway的组合使用会在后续gateway的相关文章中进行讲解。本篇文章会对sentinel的使用,sentinel与feign的组合使用进行介绍。

一 sentinel的基本使用

        在介绍sentinel的使用之前需要进行的准备工作,下载sentinel的控制台服务并启动,它的控制台是一个jar包,下载以后直接使用即可,下载地址为:Releases · alibaba/Sentinel · GitHub,在里面下载需要版本的jar包,然后启动即可。sentinel控制台的默认端口为8080,访问地址以后,会进入登录界面,用户名/密码为:sentinel/sentinel,登录以后,会出现以下的页面:

 出现上面这个页面以后,sentinel的控制台则启动完毕,需要注意的是,在没有持久化配置的时候,sentinel属于懒加载模式,当项目启动并进行性相关接口访问以后,在sentinel的控制台才会有相关服务以及资源的展示。接下来就是spring boot项目集成sentinel,以及sentinel的具体操作使用。

        新建一个spring boot项目,添加基础依赖以后,再添加以下依赖:

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

然后在项目的配置文件中新增以下配置:

spring:
  cloud:
    sentinel:
      transport:
        # sentinel控制台地址,
        dashboard: 127.0.0.1:8080
        # 默认使用8719端口,如果端口被占用会以1为长度递增,直到找到未被占用的端口
        port: 8719
      # 针对限流中的链路规则,如果要使用链路限流,则需配置为,值为false,默认为true
      web-context-unify: false

在添加上述配置的spring boot项目中添加一个简单的controller,然后编写一个接口,启动项目,访问该接口地址,在sentinel的控制台则会发现该项目。

一 限流规则

        首先我们来了解一下限流,限流的目的是为了防止当前服务在短时间进行大量的访问,超出服务的承载能力,导致服务崩溃。

        完成上述准备工作以后,我们来找到以下位置,即限流规则配置的位置:

 当我们点击流控的时候,会出现下面的弹框:

         资源名:再不进行特殊处理的情况下,则为我们的访问路径,也可以使用@SentinelResource(value="xxx")注解的方式进行自定义命名;

        针对来源:默认为default,一般不会进行修改;

        阈值类型:qps(每秒钟的接口访问数据)和并发线程数,也就是限流类型;

        单机阈值:配置阈值类型组合使用,例如阈值类型选择qps,单机阈值配置10,指的就是,当单机的qps超过10以后,触发限流规则。

        再不进行高级选项配置的时候,默认的限流策略是直接拒绝。我们可以先配置为1,看一下限流效果,连续访问该接口,即可触发限流,会出现下面的返回信息,这是sentinel默认的返回信息,后续我们会介绍sentinel的自定义返回。

 再了解完基本的限流配置以后,我们再来了解一下高级选项:

流控模式分为:

        直接:访问的地址达到限流规则的时候,直接触发限流规则;

        关联:当选择为关联以后,会出现关联资源的输入框。假设现在有两个接口,/testA和testB,在资源名为/testA的流控规则中配置为关联,关联的资源为/testB,当/testB达到配置的流控限制以后,则/testA会被限流。需要注意的是,不需要单独配置/testB的规则,当前配置的流控基本规则就是针对/testB的。

        

        链路:当选择链路的时候,会出现入口资源的输入框。如果是高版本的sentinel的话,不需要进行web-context-unify: false配置,应该是在2.2.5.RELEASE版本前后。使用链路的时候,是搭配@SentinelResource注解使用的,例如现在/testA和testB这两个接口都会访问方法base(),我们在base()方法上添加@SentinelResource("base")注解,访问/testA(/testB)以后,在簇点链路里面则会出现base的链路,使用链路的时候,我们是在base上面进行配置,而不是在接口位置进行配置,例如现在入口资源配置的是/testA,那么/testB接口即使达到限流规则也不会进行限流。

流控效果,需要注意的是,只有当阈值类型为qps时才会出现流控效果,如果阈值类型为并发线程数的话,流控效果默认为快速失败,即流控效果是针对qps进行的设置的:

        快速失败:直接失败,不进行任何处理;

        wam up(预热):当选择wam up以后会出现预热时长的输入框,预热指定是经过执行时间,该服务的qps充开始值增加到设定值,开始值的计算公式为:单机阈值/codeFactor,codeFactor的默认值为3。例如现在单机阈值配置的是20,预热时间为6s,即开始是单机阈值为7,经过6s以后单机阈值升为20。

关于这个设置预热的效果,可以在设置完流控规则以及进行相关操作以后,通过sentinel控制台的实时监控来查看。

         排队等待:当选择排队等待的时候,会出现超时时间的输出框。排队等待指的是让请求均匀的通过,而不是一次性请求。例如配置的qps是2,则意味着每500ms通过一个请求(需要注意的是,排队等待目前是不支持qps>1000的情况)。那么超时时间代表的是什么呢?这里涉及到一个计算的问题,例如超时时间配置的是10000ms,qps配置的值还是2,也就是间隔时间还是500ms,如果此时进来一个请求,发现前面还有5个请求再排队,它是第六个请求,需要等待3000ms它才会被执行,但是3000ms<10000ms,那么它就会排队等待;但是如果前面有30的请求在排队,他需要等待15500ms,此时15500ms>10000ms,那么它就会触发该限流规则,被拒绝。

        以上,则是对限流规则的介绍,大家可以根据每种情况进行模拟。并发线程可以通过jemeter进行模拟。对于关联或者链路可以通过postman的自动请求方式进行模拟,这里就不针对每种情况进行例子的编写和模拟了。 

二 熔断规则

        熔断其实是为了防止服务雪崩的情况出险,现在的服务基本都是微服务的方式部署,也就意味着会出现服务之间的调用,如果没有熔断限制,当服务之间进行服务调用,被调用的服务发生故障迟迟没有响应时,那么该IO资源则一直被占用,无法被释放,当这种请求过多时本来是服务调用者是没有问题的,但是由于被调用服务的原因到这整个服务不可用。为了防止这种情况的出险,我们可以采用sentinel的熔断规则进行处理。

        熔断规则的配置位置:

 熔断规则有三种,慢调用比例,异常比例,异常数,下面针对这三种熔断规则进行介绍。在介绍之前,还有一个知识点要了解,那就是sentinel熔断的三种状态:

        OPEN:熔断开启状态,拒绝所有请求;

        HALF_OPEN:探测恢复状态,如果接下来的一个请求能够正常访问,不触发熔断规则,那么结束熔断,否则继续熔断;

        CLOSE:熔断关闭状态,正常处理请求。

介绍完上述三种状态以后,我们来看熔断的三种策略。

慢调用比例

        点击慢调用比例的熔断规则以后,会出现以下的相关输入信息:

         资源名:即添加熔断规则请求路径,也可以通过@SentinelResource注解进行自定义。

        熔断策略:熔断策略分为三种,慢调用比例,异常比例,异常数;

        最大RT:调用允许的最大响应时间,也就是说,当实际的请求消耗时间大于该时间的话,本次调用就会归为慢调用;

        比例阈值:在此处指的是慢调用允许的比例,值的范围为0-1,例如设置的值为0.1,就以为止慢调用的比例值不能超过十分之一;

        熔断时长:当触发熔断规则以后,服务在指定时间内处于服务拒绝,也就是上面说的OPEN状态;

        最小请求数:只有当请求数量大于该值,才会触发熔断规则的校验,如果小于该值,则不进行熔断校验;

        统计时长:统计指定时间范围之内的请求数据。

        上面是熔断规则各个字段的介绍,不同的熔断策略,大部分参数是一样的含义,只有部分参数是熔断策略独自拥有的。对于慢调用比例,最大RT以及比例阈值是用来配置慢调用信息的配置项。

        下面用一组具体配置来说明一下它代表的含义,最大RT为500,比例阈值为0.4,熔断时长1,最小请求数为5,统计时长为1000,它代表的含义是,统计1s内的请求情况,如果1s内的请求数量小于5,则熔断状态处于CLOSE;如果请求数量大于5,例如有10个请求,那么统计这10个请求中响应时间大于0.5s的请求数,如果大于0.5s的请求数小于4(0.4*10),那么熔断状态为CLOSE,否则为OPEN状态,OPEN状态会持续1s,当熔断时间达到1s以后,熔断状态为HALF_OPEN状态,如果接下来的一个请求,响应时间小于0.5s,则熔断状态恢复为CLOSE状态,否则继续重复上面的状态变更,即熔断处于OPEN状态1s,然后变为HALF_OPEN状态。

        模拟该情况的时候,可以利用sleep方法进行模拟,通过线程睡眠模拟慢响应。

2 异常比例

        异常比例:发生异常的请求占总请求的比例。

        还是以一个具体的例子来说明,比例阈值为0.4,熔断时长1,最小请求数为5,统计时长为1000,它代表的含义是,统计1s内的请求情况,如果1s内的请求数量小于5,则熔断状态处于CLOSE;如果请求数量大于5,例如有10个请求,那么统计这10个请求中发生异常的请求数,如果发生异常的请求数小于4(0.4*10),那么熔断状态为CLOSE,否则为OPEN状态,OPEN状态会持续1s,当熔断时间达到1s以后,熔断状态为HALF_OPEN状态,如果接下来的一个请求,响应时间小于0.5s,则熔断状态恢复为CLOSE状态,否则继续重复上面的状态变更,即熔断处于OPEN状态1s,然后变为HALF_OPEN状态。

异常数

         异常数:出现异常的请求数量。

        还是以一个具体的例子来说明,异常数为:4,熔断时长1,最小请求数为5,统计时长为1000,它代表的含义是,统计1s内的请求情况,如果1s内的请求数量小于5,则熔断状态处于CLOSE;如果请求数量大于5,例如有10个请求,那么统计这10个请求中发生异常的请求数,如果发生异常的请求数小于4,那么熔断状态为CLOSE,否则为OPEN状态,OPEN状态会持续1s,当熔断时间达到1s以后,熔断状态为HALF_OPEN状态,如果接下来的一个请求,响应时间小于0.5s,则熔断状态恢复为CLOSE状态,否则继续重复上面的状态变更,即熔断处于OPEN状态1s,然后变为HALF_OPEN状态。

三 sentinel限流规则的其它介绍

热点规则

        我们在第一部分介绍的限流规则中,只是对请求资源进行整体的限流规则,如果我们要更细粒度的进行限流的话,就要用到热点规则。例如我们要限制某一个时间段内,指定热销产品的的购买次数进行限制。热点规则指的就是针对一个请求路径,请求参数中包含热点数据的进入限流规则,而未包含热点数据的请求不进入热点数据。通过下图做一个说明:

 接下来我们看一下如何进行配置:

 

         资源名:请求路径地址;

        限流模式:目前仅支持qps,不可修改;

        参数索引:指的是接口中参数索引,索引从0开始;

        在参数例外项中还有一组参数:

        参数类型:目前参数类型支持8种:byte,short,int,long,float,double,String;

        参数值:设置热点数据;

        限流阈值:该热点数据的限流qps值。

        上面为对热点规则的配置介绍,有兴趣的同学可以自己试一下。

2 授权规则

        授权规则指的是当前资源允许哪些资源访问,不允许哪些资源访问,它是一个黑白名单机制,它的配置入口如下:

 

3 系统规则 

        我们上面介绍的那些规则,其实是属于细粒度的限流,可以认为是api级别的限流,但是系统规则属于是粗粒度的限制,它是针对整个服务而言的。它的配置入口如下:

 

LOAD:以系统1分钟的平均负载作为启发指标,进行自适应系统保护。当系统的1分钟平局负载超过设定的阈值,并且系统当前的并发线程数超过估算的系统容量时才会触发系统保护,系统容量=maxQps(最大qps)*minRt(最小响应时间)估算得出。设定参考值:cup cores (cpu核数)* 2.5。

RT:响应时间

线程数,入口qps以及cpu利用率就是字面意思

二 sentinel的进阶使用

一 自定义响应信息

        在我们使用sentinel进行限流或者熔断的时候,如果不进行配置,会采用sentinel的默认限制信息,例如显示信息为:Blocked by Sentinel (flow limiting),这种显示方式对于生产环境面向客户的话,它是很不友好的,我们可以利用@SentinelResouce注解来进行自定义数据返回。

        我们以下面这段简单代码为例进行说明:

        新建一个异常处理类,里面包含两个方法,一个是触发限流规则时的提示,一个是发生异常时的提示:

// 自定义异常处理类
public class SelfSentinelHandler {
    // 当资源触发限流或者熔断规则的时候,返回的错误提示信息
    public static String limite(BlockException e){
        return "sentinel limite";
    }
    
    // 当调用资源发生异常时,返回的错误提示信息
    public static String systemError(BlockException e){
        return "system error";
    }
}

        当上面的自定义错误提示信息类开发完成以后,接下来就是调用资源处的配置:

@GetMapping("/test")
@SentinelResource(blockHandlerClass = SelfSentinelHandler.class, blockHandler = "limite"
    , fallbackClass = SelfSentinelHandler.class, fallback = "systemError"
    , exceptionsToIgnore = {IOException.class, InterruptedException.class})
public String test(){
    return "hello sentinelC";
}

在这里我们用到了@SentinelResource注解,下面针对注解中的各个属性进行相关解释:

        blockHandlerClass:触发限流或者熔断规则时,处理提示信息的类;

        blockHandler:触发限流或者熔断规则时,调用的方法;

        fallbackClass:调用接口发生异常时,处理提示信息的类;

        fallback:调用接口发生异常时,调用的方法;

        exceptionsToIgnore:调用接口发生异常时,忽略的异常信息,这些异常可以直接进行返回。

        需要注意,因为我们是在其它类中定义的相关异常处理方法,因此这些方法我们要使用static进行修饰;当然如果不配置blockHandlerClass,fallbackClass,只配置blockHandler,fallback时,这些方法和当前接口开发在同一个类中,不需要使用static进行修饰。

二 配置持久化(nacos)

        sentinel使用的是懒加载,只有对应的api被访问以后才会出现对应的链路信息,然后设置其限流熔断规则,当项目重启以后,我们配置的限流熔断规则就会消失,显然,在生产环境环境中,这种配置方式是不合适,这就涉及到了限流熔断规则配置的持久化,这里我们配合nacos进行持久化。

        在介绍通过nacos配置持久化之前,我们先对持久化进行一个整体的了解。目前sentinel支持的持久化有两种模式:

        1.拉模式,也就是客户端通过定时任务的方式主动拉取流控规则,这种方式有一种致命的缺点,即在流控规则发生变更的时候,客户端获取流控规则是由延时的。使用这种方式的配置,目前有eurake,动态数据源等;

        2.推模式,客户端通过注册监听事件的方式实时监控流控规则的变化,目前sentinel支持的推模式的数据源有:zookeeper,apollo,nacos,redis等。

        本文介绍的是使用nacos,如果要了解其它模式,可以参考sential的官方文档:流控规则持久化

我们先看一下持久化流控规则的原理(针对nacos):

         正常情况下,nacos与sentinel控制台之间应该是互相影响的,也就是说,在nacos控制台修改流控规则,sentinel控制台的流控规则同步修改,这一点是目前实现的;sentinal控制台修改流控规则,也应该同步修改到nacos中,但是这一点目前是没有实现的,大家在使用的时候一定要注意,如果要永久化的修改流控规则,一定要在nacos中进行修改。

首先,我们需要先引入依赖:

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
            <version>1.8.1</version>
        </dependency>

然后再配置文件中,添加以下配置:

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 172.30.10.103:8848
    sentinel:
      web-context-unify: false
        # sentinel控制台的访问信息
      transport:
        dashboard: 172.30.10.103:8080
        port: 8719
      # sentinel持久化的相关配置
      datasource:
        nacos:
          nacos:
            # nacos服务端地址
            serverAddr: 172.30.10.103:8848
            # naocs命名空间
            namespace: 4b57e563-2039-42f4-86b1-9c4c7cf58bfc
            # nacos组信息
            groupId: DEFAULT_GROUP
            # 在nacos中存放持久化配置的文件名称
            dataId: sentinel-config.json
            # 持久化的流控规则类型,目前支持flow,degrade,param-flow,system,authority,gw-flow,gw-api-group这几种,他们具体代表什么,我们后续再源码章节会进行介绍
            ruleType: flow

完成上述配置以后,接下来就是要去到nacos的指定位置,配置持久化文件

 因为在项目中我们配置的ruleType是flow,那么我们这里的配置信息为:

[
    {
        "resource": "/sentinel/config/demo",
        "limitType": "default",
        "grade": "1",
        "count": "1",
        "strategy": "0",
        "controlBehavior": "0",
        "clusterMode": false
    }
]

resource:资源名,对应api的访问地址(@SentinelResource注解指定的名称);

limitType:来源应用,默认为default;

grade:阈值类型,0-线程数,1-qps;

count:单机阈值;

strategy:流控模式,0-直接,1-关联,2-链路;

controlBehavior:流控效果,0-快速失败,1-warm up,2-排队等待;

clusterMode:是否集群,true/false

        需要注意的是,配置文件中ruleType不同,那么在nacos配置文件中的字段则不相同,根据实际情况进行配置。

        当我们完成上述配置以后,启动我们的spring boot服务,访问对应的api,这时候我们会发现在sentinel控制台中,有我们对应的流控规则配置。

三 OpenFeign使用介绍

        为什么要在这里介绍OpenFeign呢?一个原因是OpenFeign作为一个服务调用组件,它比较简单,不需要单开一篇文章进行介绍;还有一个原因是,我们在介绍熔断机制的时候说过,它主要针对的就是服务之间的调用。而在微服务架构中,我们常用的一种服务之间调用则是OpenFeign。需要注意一点,使用OpenFeign一定要搭配注册中心进行使用,它是spring cloud里面的一个组件。我们这里使用的注册中心组件为nacos。

        OpenFeign的底层使用了HttpClient进行服务调用,并且通过前文我们知道nacos本身已经继承了ribbon进行负载均衡,这里针对集群调用也不需要额外配置。接下来我们介绍一下OpenFeign的使用,如果要使用OpenFeign,那么肯定存在服务提供者以及服务消费者两方。对于服务提供者,我们不需要进行特殊处理,只需要创建基本的spring boot项目,然后注册到nacos中即可,本文介绍的是sentinel的使用,那么再加上sentinel的相关配置,用于配置熔断规则。接下来我们介绍一下服务消费方的处理,需要主要一定要添加nacos作为注册中心的相关依赖,基于nacos作为配置中心。

        首先,还是添加OpenFeign的相关依赖:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        其次,在启动类中添加启动OpenFeign的注解,也可以在启动类型添加打印OpenFeign的日志的bean对象:

@SpringBootApplication
@EnableDiscoveryClient
// 使用openFeign,如果不添加该注解,无法使用
@EnableFeignClients
public class FeignConsumer9003Application {

    public static void main(String[] args) {
        SpringApplication.run(FeignConsumer9003Application.class, args);
    }
    
    // 打印openFeign的注解
    @Bean
    Logger.Level feignLoggerLevel(){
        //开启详细日志,这里的日志级别有四种,默认为NONE-不打印任何日志
        // BASIC:记录请求方法,URL,响应状态码以及执行时间
        // HEADERS:除了BASIC中定义的信息之外,还有请求和响应的头信息
        // FULL:除了HEADERS级别的信息以外,还有请求和响应的正文以及元数据
        return Logger.Level.FULL;
    }
}

        然后,在配置文件中添加相关配置,nacos的配置是必须的,关于OpenFeign的配置并不是必须的,他是对一些参数的特殊设置

// 因为openFeign在调用时通过ribbon作为负载均衡,因此OpenFeign的超时时间也就是ribbon的超时时间
ribbon:
  # 指的是建立连接后从服务器读取到可用资源所用的时间
  ReadTimeout: 5000
  #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
  ConnectTimeout: 5000
// openFeign的日志打印级别以及对应的类型信息
logging:
  level:
    org.springframework.stereotype.Service.OpenfeignService: debug

        最后,则是代码的编写,首先需要编写一个接口,服务消费者就是通过调用这个接口的相关方法来实现调用服务消费者。

@Service
// 该注解为OpenFeign的相关注解,注解里面的值为服务提供者注册到nacos中的服务名
@FeignClient("provider-service")
public interface OpenfeignService {
    // 服务提供者提供的请求地址以及请求方式
    @GetMapping("/provider/product/{id}")
    // 方法签名,方法入参以及返回值一定要与服务提供者中对应接口完全一致
    String getProduct(@PathVariable("id") Integer id);
}

接下来就可以通过bean注入的方式来进行调用,在服务消费者中,通过本地方法的调用来实现远程调用,然后启动服务提供者以及服务消费者,然后访问服务消费者中的相关接口,在调用到服务提供者,此时再sentinel的控制台,则会出现对应的服务,我们即可配置对应的熔断规则。

猜你喜欢

转载自blog.csdn.net/weixin_38612401/article/details/125906939