SpringCloudAlibaba-服务容错Sentinel(进阶)

一:基本概念

1.1 资源:就是Sentinel要保护的东西,它可以是Java应用程序中的任何内容,可以是一个服务,也可以是一个方法,甚至可以是一段代码

1.2 规则:用来定义如何进行保护资源的

二:重要功能

Sentinel的主要功能就是容错,主要体现在下面三个类型:

2.1 流量控制

流量控制在网络传输中是一个常用的概念,它用于调整网络包的数据。任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。

2.2 熔断降级

当检测到调用链路中某个资源出现不稳定的表现,例如请求响应时间长或异常比例升高的时候,则对这个资源的调用进行限制,让请求快速失败,避免影响到其他的资源而导致级联故障。

Sentinel对这个问题采取了两种措施

1:通过并发线程数进行控制

Sentinel通过限制资源并发线程的数量,来减少不稳定资源对其他资源的影响。当某个资源出现不稳定的情况下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆积。当线程数

在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才开始继续接收请求。

2:通过响应时间对资源进行降级

当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢复。

2.3 负载均衡保护

当系统负载均衡较高时,如果还持续让请求进入可能会导致系统崩溃,无法响应。在集群环境下,会把本应这台机器承载的流量转发到其他的机器上去。如果这个时候其他的机器也处在一个边缘状态的时候

Sentinel提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求。

三:Sentinel规则

3.1 流控规则

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

第一步:点击簇点链路,我们就可以看到访问过的接口地址,然后点击对应的流控按钮,进入流控规则配置页面。新增流控规则界面如下:

  

 

  • 资源名:唯一名称,默认是请求路径,可自定义
  • 针对来源:指定对哪个微服务进行限流,默认default,意思是不区分来源,全部限制
  • 阈值类型\单机阈值:
  • QPS(每秒请求数量):当调用接口的QPS达到阈值的时候,进行限流
  • 线程数:当调用接口的线程数达到阈值的时候,进行限流
  • 是否集群:本例不做集群

上一章文末简单示例就是以QPS来配置的。

3.1.1 配置流控模式

点开高级选项  如下图

  

 

可以看到有三种流控模式:直接、关联、链路。接下来我们逐一演示

直接流控模式:最简单的模式,当指定接口到达限流条件时开启限流。参考上章案例

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

第一步:配置限流规则,将流控模式设置为关联,关联资源设置为/sentinel/mesg2

  

 

第二步:通过jemeter访问mesg2,达到限流状态

  

 

第三步:访问/sentinel/mesg1,会发现已经被限流

  

 

链路流控模式

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

配置流控效果

快速失败(默认):直接失败,抛出异常,不做任何额外的处理,是最简单的效果

Warm up:它从开始阈值到最大QPS阈值会有一个缓冲阶段,一开始的阈值是最大QPS阈值的1/3,然后慢慢增长,直到最大阈值,适用于将突然增大的流量转换为缓步增长的场景。

排队等待:让请求以均匀的速度通过,单机阈值为每秒通过数量,其余的排队等待; 它还会让设置一个超时时间,当请求超过超时间时间还未处理,则会被丢弃。

3.2 降级规则:

当满足什么条件的时候,对服务进行降级。Sentinel提供了三个衡量条件:

平均响应时间:当资源的平均响应时间超过阈值(以 ms 为单位)之后,资源进入准降级状态。如果接下来 1s 内持续进入 5 个请求,它们的 RT都持续超过这个阈值,

            那么在接下的时间窗口(以 s 为单位)之内,就会对这个方法进行服务降级。

  

 

异常比例:当资源的每秒异常总数占通过量的比值超过阈值之后,资源进入降级状态,即在接下来的时间窗口之内,对这个方法的调用都会自动返回。异常比例的阈值范围是[0.0,1.0]

第一步:模拟异常

    int i = 0;
    @RequestMapping("/mesg2")
    public String message2(){
        i++;
        if(i%3 == 0){
            throw new RuntimeException();
        }
        return "message2";
    }

第二步:设置异常比例为0.25

  

3.3 热点规则:

一种更细粒度的流控规则,它允许将规则具体到参数上。

第一步:代码编写

@RequestMapping("/mesg3")
@SentinelResource("mesg3")
public String message3(String name,Integer age){

return "message3="+name+"_"+age;
}

第二步:配置热点规则

第三步:分别用两个参数访问,会发现只对第一个参数限流了

 热点key增强使用:参数例外项允许对一个参数的具体值进行流控...(此处不做演示了)

3.4 授权规则:

来源访问控制根据资源的请求来源限制资源 是否通过

若配置白名单,则只有请求来源定位于白名单内时才可通过;

若配置黑名单,则请求来源于黑名单时不通过,其余请求通过;

第一步:自定义来源处理规则

@Component
public class RequestOriginParserDefinition implements RequestOriginParser {
    @Override
    public String parseOrigin(HttpServletRequest request) {
        String serviceName = request.getParameter("serviceName");
        return serviceName;
    }
}

第二步:配置授权规则

这个配置的意思是只有serviceName=pc不能访问(黑名单)

 

第三步:访问接口查看效果

 

 3.5 系统规则

  系统保护规则是从应用级别的入口流量进行控制,从单台机器的总体 Load、RT、入口 QPS 、CPU使用率和线程数五个维度监控应用数据,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量 (进入应用的流量) 生效。

  • Load(仅对 Linux/Unix-like 机器生效):当系统 load1 超过阈值,且系统当前的并发线程数超过系统容量时才会触发系统保护。系统容量由系统的 maxQps * minRt 计算得出。设定参考值一般是 CPU cores * 2.5。
  • RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
  • 线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
  • 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
  • CPU使用率:当单台机器上所有入口流量的 CPU使用率达到阈值即触发系统保护。

 四:Feign整合Sentinel

4.1 引入sentinel依赖

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

4.2  application.yml配置中开启Feign对Sentinel的支持

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

4.3  创建容错类

/**
 * 容错类要求必须实现被容错的接口,并为每个方法实现容错方案
 */
@Component
@Slf4j
public class ProductApiFallback implements ProductApiService {
    @Override
    public Product getByPid(Integer pid) {
        Product product = new Product();
        product.setPname("服务容错");
        product.setPid(-1);
        return product;
    }
}

4.4  对feign管理的接口指定容错类

@FeignClient(value = "service-product",fallback = ProductApiFallback.class)//声明调用的提供者的name
public interface ProductApiService {

    /**
     * 指定调用提供者的哪个方法
     * @FeignClient+@GetMapping 就是一个完整的请求路径 http://service-product/product/{pid}
     * @param pid
     * @return
     */
    @GetMapping("/product/{pid}")
    Product getByPid(@PathVariable("pid") Integer pid);


}

4.5 停止或异常shop-product服务,请求接口测试

 

posted @ 2020-08-19 16:03  不二尘  阅读(954)  评论(0编辑  收藏  举报