sentinel的原理以及基本使用

简介: sentinel的原理以及基本使用

一,Sentinel引入原因

1,分布式系统遇到的问题

通常情况下,一个业务逻辑往往会依赖多个服务,如一个商品展示服务会依赖商品服务,价格服务,商品评论服务等。在用户发起请求之后,在一个商品详情服务,会通过一个创建线程池,比如说里面创建100个线程,用来加载商品服务,价格服务,商品评论服务。

当用户去大量评论的时候,那么线程全部会在这个商品评论服务上面,那么会导致其他服务不可用,那么就会造成一个服务雪崩状态。

造成服务雪崩的原因

1,大流量请求:如在秒杀的时候,准备不充分,瞬间大量请求进来,导致服务提供者不可用

2,硬件故障:服务器出现宕机情况

3,出现缓存击穿:热点数据同一时间失效

2,解决服务雪崩问题

2.1,超时机制

加入一个超时机制,当一个服务在一定时间内没有得到响应,就会释放资源,从而抑制资源耗尽的问题。

2.2,服务限流

限制请求核心服务提供者的流量,使大流量拦截在核心服务之外。可以通过线程池加队列的方式实现,队列可以是一个阻塞队列。

2.3,服务熔断

和现实中的断路器一样,用于监控电路情况,如果发现电路电流异常,就会跳闸,从而防止这个电路被烧毁。

断路器的基本原理:就是说在一段时间内,如果发现失败的次数或者失败率达到一个阈值的一个情况,那么就会出现一个跳闸的情况,这个断路器就会打开,请求就会直接return返回;跳闸一段时间之后,断路器就会进入一个半开的状态,就是一个瞬时态,允许发起一次请求,如果成功,则断路器关闭,走原来的正常流程,如果不成功,那么这个断路器又会打开 ,一段时间之后又会进入一个半开的状态,如此循环下去。

c60ddcb7965d47349eb015d2d17cfe08.png


2.4,服务降级

有熔断就一定会有降级。就是当某个服务熔断之后,服务将不再被调用,此时客户端可以自己准备一个本地的fallback(回退)回调,返回一个缺省值。或者流量前面的流量太大,后面的服务处理能力不足,会对前面的服务进行一个降级操作


二,Sentinel工作原理

1,什么是Sentinel

Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。只要通过Sentinel API 定义的代码,就是资源,能够被 Sentinel保护起来


2,sentinel控制台安装

1,下载这个jar包,在本地跑即可。


[ Releases · alibaba/Sentinel · GitHub ]( Releases · alibaba/Sentinel · GitHub )

63648ab3b78242118707497be95c7515.png

2,启动jar包

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.5.jar

3,默认端口为8080,输入localhost:8080,然后登录, 默认用户名和密码都是 sentinel

6dc27360797a40008a62f016baeab1cb.png


4,登陆完成之后,可以看到这个sentinel的主界面。可以发现里面有大量的规则,比如说流控规则,熔断规则,热点规则,授权规则等。


32dfdb4483574f40a8863193dc403b7d.png

3,客户端连接这个sentinel控制台

1,需要的依赖

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

2,yml配置文件

spring:
  cloud:
    sentinel:
      transport:
    #注册的地点
        dashboard: 127.0.0.1:8080
      filter:
        enabled: false

4,sentinel工作流程

4.1,资源

由应用程序提供的服务,比如说是一个接口,甚至是一段代码等。就是说只要被这个sentinel API定义了的代码,就是一个资源,就可以被这个sentinel保护起来。所有的资源都对应一个资源名称(resourceName),每次资源在调用时都会创建一个 Entry 对象


4.2,规则

就是最绕这个资源所设定的一些规则,如一些限流规则,降级规则,熔断规则等。并且所有的规则可以动态调整。


4.3,插槽

因此在这个资源创建的时候Entry 创建的时候,同时也会创建一系列功能插槽(slot chain),这个插槽有不同的职责。

FlowSlot:限流

DegradeSlot:熔断

AuthoritySlot:授权


4.4,工作流程

模拟一个工作流程,对一个接口进行一个限流操作,大致流程如下,首先会定义一个资源,其次会对这个资源定义一个规则,最后会去检测这个规则是否生效。


1,传统api的方式

private static final String RESOURCE_NAME = "getUserMessage";
#这个接口就是一个限流的一个对象
@RequestMapping(value = "/getUserMessage")
public String getPrice(){
    Entry entry = null;
    try{
        //资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。
        //会将这个资源封装成一个Entry的一个对象
        entry = SphU.entry(RESOURCE_NAME);
    }catch (BlockException e1) {
        //限流异常,如果达到一个阈值,就会进入这个异常
      return "被流控了!";
    }catch (Exception ex) {
        //正常的业务逻辑的异常捕获
        Tracer.traceEntry(ex, entry);
    } finally {
        //关闭资源
        if (entry != null) {
            entry.exit();
        }
    }
    return null;
}

规则可以在容器初始化的时候就可以进行一个制定,通过这个**@PostConstruct**注解提前对这个规则进行一个初始化。

@PostConstruct
private static void initFlowRules(){
    List<FlowRule> rules = new ArrayList<>();
    FlowRule rule = new FlowRule();
    //设置受保护的资源
    rule.setResource(RESOURCE_NAME);
    // 设置流控规则 QPS,每秒的请求数
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    // 设置受保护的资源阈值,每秒只能访问一次
    rule.setCount(1);
    rules.add(rule);
    // 加载配置好的规则
    FlowRuleManager.loadRules(rules);
}

这样的话就简单的实现了一个限流的一个应用。同时也可以再控制台上面看到

9f7a08e7ddc34576b33e060982e537e6.png


2,注解的方式

@RequestMapping("/info/{id}")
@SentinelResource(value = "userinfo",
        blockHandlerClass = DefaultSentinelHandler.class, //用于流控的配置类
        blockHandler = "handleException2", //流控类里面的配置方法
        fallbackClass = DefaultFallback.class, //回调方法
        fallback = "fallback" //回调类
)
public R info(@PathVariable("id") Integer id){
    User user = userService.getById(id);
    if(id==4){
        throw new IllegalArgumentException("异常参数");
    }
    return R.ok().put("user", user);
}
//流控类里面的配置方法
public R handleException2(@PathVariable("id") Integer id, BlockException exception){
    return R.error(-1,"===被限流降级啦===");
}
//回调类里面的方法
public R fallback(@PathVariable("id") Integer id,Throwable e){
    return R.error(-1,"===被熔断降级啦==="+e.getMessage());
}

也可以使用使用一个统一管理的配置类,将几种规则统一管理

@Slf4j
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        log.info("BlockExceptionHandler BlockException================"+e.getRule());
        R r = null;
        if (e instanceof FlowException) {
            r = R.error(100,"接口限流了");
        } else if (e instanceof DegradeException) {
            r = R.error(101,"服务降级了");
        } else if (e instanceof ParamFlowException) {
            r = R.error(102,"热点参数限流了");
        } else if (e instanceof SystemBlockException) {
            r = R.error(103,"触发系统保护规则了");
        } else if (e instanceof AuthorityException) {
            r = R.error(104,"授权规则不通过");
        }
        //返回json数据
        response.setStatus(500);
        response.setCharacterEncoding("utf-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        new ObjectMapper().writeValue(response.getWriter(), r);
    }
}

5,规则

5.1,流控规则

4cca7938717e4f86b8d9da59dc63e9dc.png


主要是通过这个应用流量的qps或者并发线程两个指标,当达到阈值的时候对这个流量进行一个控制,避免大流量的冲击,从而保证这种应用的高可用


5.1.1,流控模式

流控模式主要有直接模式,关联模式和这个链路模式。


直接模式

正常来讲都是使用这个直接模式,就是说当这个资源调用达到设置的阈值后,则会直接被流控抛出异常。


关联模式

当两个资源之间具有资源争抢或者依赖关系的时候,这两个资源便具有了关联。比如对数据库同一个字段的读操作和写操作存在争抢。关联的话可以设置这个关联的资源,如关联一个接口。

e4196bb27599433b8ced13f5c6648bc7.png


链路模式

根据这个调用链路进行一个限流操作


5.1.2,流控效果

就是当这个qps超过某个阈值的时候,对这个流量控制采取的一系列措施。主要有快速失败,预热,匀速排队等具体实现。


快速失败

默认方式就是这种。就是说当这个qps达到这个阈值之后,其他新进来的请求就会立马拒绝策略,通过一个抛异常的方式实现。适用于一些压测后,了解系统水平能力的场景


预热

给一个缓冲时间,让流量缓慢增加,在一定时间内组件增加到这个阈值的上限,相当于给系统一个预热时间,避免系统直接被大流量压垮。


匀速排队

严格控制请求通过的时间,就是让这个请求匀速的通过,对应的是漏桶算法。


5.2,熔断规则

主要是针对链路中一些不稳定的资源进行一个熔断降级,就是暂时切断一些不稳定的调用,避免因为局部不稳定的因素导致整体服务的雪崩。

448e4c5e2dd14474b115e4af49b6ea2f.png


5.2.1,熔断策略

主要有慢调用比例,异常比例,异常数等


慢调用比例


就是说会给这个服务的响应设置一个时间,如果外面的服务来请求的时候,该服务的响应时间大于设置的时间,则统计为一个慢调用。如果单位时间内,请求个数大于这个最小请求数,并且这个慢调用的个数或者比例超过这个阈值的时候,那么该服务就会进入到一个熔断的状态,相当于一个全开状态;一段时间后,会发起一个很小的请求,相当于一个半开状态,会去判断这个响应的时间,如果还是超过最大时间,那么又会进入全开状态,否则执行正常业务流程


异常比例

就是在单位时间内,请求个数大于这个最小请求数,并且这个异常的比例大于这个设置的阈值,那么就会触发这个熔断机制。


异常数

就是在单位时间内,请求个数大于这个最小请求数,并且这个异常个数大于这个设置的阈值,那么就会触发这个熔断机制。


5.3,热点规则

热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流

4e8d6b1789b5424eb24e12ed0178dbd5.png

这个参数值只支持这个基本数据类型,并且只能通过这个@SentinelResource这个注解生效。


5.4,系统规则

会从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性


6e837d05778c4b7b95d54f6dd0058a44.png

5.5,授权规则

主要是用于这个授权,增加这个黑白名单。会根据调用来源来判断该次请求是否允许放行,白名单会进行一个放行操作,黑名单不放行。

2ba35f0495e14217bfde657c3897456d.png


5.6,集群规则

集群流控可以精确地控制整个集群的调用总量,结合单机限流兜底,可以更好地发挥流量控制的效果。

适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性

f2eb6a7232414a1f897e010a47532c05.png

相关文章
|
缓存 负载均衡 Dubbo
Sentinel 集群限流设计原理
Sentinel 集群限流设计原理
Sentinel 集群限流设计原理
|
自然语言处理 监控 Cloud Native
精华推荐 |【深入浅出Sentinel原理及实战】「原理探索专题」完整剖析Alibaba微服务架构体系之轻量级高可用流量控制组件Sentinel(1)
精华推荐 |【深入浅出Sentinel原理及实战】「原理探索专题」完整剖析Alibaba微服务架构体系之轻量级高可用流量控制组件Sentinel(1)
608 0
精华推荐 |【深入浅出Sentinel原理及实战】「原理探索专题」完整剖析Alibaba微服务架构体系之轻量级高可用流量控制组件Sentinel(1)
|
3月前
|
监控 算法 Java
sentinel 服务限流工作原理
sentinel 服务限流工作原理
|
4月前
|
监控 NoSQL 程序员
Redis 高可用篇:你管这叫 Sentinel 哨兵集群原理
Redis 高可用篇:你管这叫 Sentinel 哨兵集群原理
78 5
|
4月前
|
监控 BI Sentinel
深入理解Sentinel系列-2.Sentinel原理及核心源码分析(下)
深入理解Sentinel系列-2.Sentinel原理及核心源码分析
46 0
|
4月前
|
存储 监控 测试技术
深入理解Sentinel系列-2.Sentinel原理及核心源码分析(上)
深入理解Sentinel系列-2.Sentinel原理及核心源码分析
88 0
|
5月前
|
算法 Java BI
Sentinel为什么这么强,我忍不住扒了扒背后的实现原理
大家好,我是三友~~ 最近我在整理代码仓库的时候突然发现了被尘封了接近两年之久的Sentinel源码库 两年前我出于好奇心扒了一下Sentinel的源码,但是由于Sentinel本身源码并不复杂,在简单扒了扒之后几乎就再没扒过了 那么既然现在又让我看到了,所以我准备再来好好地扒一扒,然后顺带写篇文章来总结一下。
Sentinel为什么这么强,我忍不住扒了扒背后的实现原理
|
9月前
|
算法 Java Sentinel
sentinel架构底层原理剖析详解
sentinel架构底层原理剖析详解
102 0
|
10月前
|
存储 负载均衡 监控
Sentinel工作原理
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。 只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
58 0
|
11月前
|
自然语言处理 算法 Java
深扒Sentinel背后的实现原理之后,我终于明白它为什么这么强了
最近我在整理代码仓库的时候突然发现了被尘封了接近两年之久的Sentinel源码库 两年前我出于好奇心扒了一下Sentinel的源码,但是由于Sentinel本身源码并不复杂,在简单扒了扒之后几乎就再没扒过了 那么既然现在又让我看到了,所以我准备再来好好地扒一扒,然后顺带写篇文章来总结一下。