SpringBoot整合Sentinel实现服务限流、熔断

Sentinel是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。
详细介绍请看:https://github.com/alibaba/Sentinel/wiki

一、Sentinel服务的安装

1、Sentinel下载

项目地址:https://github.com/alibaba/Sentinel

Sentinel结构简介:

Sentinel整体项目由多个组件构成,但主要分为sentinel-core和sentinel-dashboard,两者分别作为Sentinel的连接服务和管理控制台。使用Sentinel,我们需要先下载sentinel-dashboard管理控制台,然后在微服务中依赖sentinel-core连接管理控制台。

sentinel-dashboard下载:

下载有两种方式,第一种可以直接下载Jar包部署使用。
SpringBoot整合Sentinel实现服务限流、熔断_第1张图片
第二种就是下载源代码,自己打包使用,不过注意,sentinel-dashboard使用Maven管理整个项目,需要将整体项目全部下载打包。
SpringBoot整合Sentinel实现服务限流、熔断_第2张图片
两种方式没有区别,生成的Jar包完全相同!

2、sentinel-dashboard部署

由于sentinel-dashboard为SpringBoot项目,所以直接运行即可:

java -Dserver.port=8081 -jar sentinel-dashboard.jar #由于默认端口为8080,所以更改端口为8081
nohup java -Dserver.port=8081 -jar sentinel-dashboard.jar > log.log 2>&1 &^C  #使用此命令后台运行服务

如果无法访问请检查防火墙:

firewall-cmd --add-port=8081/tcp --permanent #将8081加入白名单
firewall-cmd --reload #刷新防火墙

此时输入连接访问即可,账号密码均为sentinel:
SpringBoot整合Sentinel实现服务限流、熔断_第3张图片

SpringBoot整合Sentinel实现服务限流、熔断_第4张图片

接下来服务连接后,我们就可以使用此控制台控制服务的流量信息!

二、构建测试项目

1、搭建SpringBoot项目

Sentinel作为SpringCloudAlibaba中的项目,主要服务于微服务架构,但也可以在非微服务中使用,我们现在就用一个普通的SpringBoot项目进行测试。

SpringBoot整合Sentinel实现服务限流、熔断_第5张图片

2、导入依赖,配置地址

在项目中导入依赖:


      com.alibaba.cloud
      spring-cloud-starter-alibaba-sentinel
      2021.1  

在配置文件中配置以下信息:

spring:
  cloud:
    sentinel:
      transport:
        port: 8719 #与sentinel-dashboard通信端口,如果被占用,会自动向后扫描
        dashboard: 10.10.2.188:8081 #sentinel-dashboard地址
  application:
    name: sentineldemo #项目名称

此处注意:8179并非sentinel-dashboard开放的端口,而是微服务开放的端口,sentinel-dashboard需要访问微服务的8179端口进行限流设置,所以务必确保sentinel-dashboard可以访问到服务的8179端口,否则会无法监控!

3、启动测试项目

项目配置好后即可启动项目,此处注意sentinel-dashboard采用懒加载机制,只有当我们的服务北方问后,sentinel-dashboard中才可以显示,所以请先访问一次,再查看控制台结果:
在这里插入图片描述
SpringBoot整合Sentinel实现服务限流、熔断_第6张图片
此时就可以查看实时流量,进行流量控制!

三、流量控制规则详解

SpringBoot整合Sentinel实现服务限流、熔断_第7张图片
进入访问控制台后,点击“簇点链路”即可查看服务被访问的URL,使用左侧按钮进行流控设置!

@SentinelResource(“标识符”)注解

SpringBoot整合Sentinel实现服务限流、熔断_第8张图片
该注解用于给一个Controller设置一个唯一标识符,在设置限流熔断规则时,可以使用该标识符!
SpringBoot整合Sentinel实现服务限流、熔断_第9张图片
注意:在熔断和限流中可以直接不使用此注解,直接使用URL也可以,但注意,使用注解和不使用注解的异常处理完全不同,建议全部使用,如果不使用,则建议统一完全不使用!

本教程以下操作全部使用该注解,资源ID为与url相同

1、限流

点击“流控”,即可进行限流设置:
SpringBoot整合Sentinel实现服务限流、熔断_第10张图片

阈值类型:

  • QPS:每秒最大访问次数(比如:设置QPS的阈值为5,则一秒内如果超过5次访问,则达到限流标准,开始限流)
  • 线程数:服务最大的线程数量(比如:线程数的阈值为5,则如果同时超过5人同时访问该资源并都在执行中,达到限流标准)

流控模式:

  • 直接:如果该资源访问超过限流标准,则对自身进行限流(比如:我对/test进行QPS为5的限流,则如果/test请求一秒内被访问超过5次,则开始保护,/test在这一秒内无法访问。)
  • 关联:如果被关联的资源访问超过阈值,则限流自身(比如:我对/test进行QPS为5的限流,关联资源为/hello,则如果/hello请求一秒内被访问超过5次,则开始保护,/test在这一秒内无法访问)
    在这里插入图片描述
  • 链路:只记录从特定链路的流量,如果达到阈值,则进行限流,其他流量不记录
    在这里插入图片描述
    流控效果
  • 直接失败:返回错误信息
  • 排队等待:按流控阈值逐条处理,但如果超过等待时间,则失败
    在这里插入图片描述
  • Warm Up :对限流进行预热,刚开始以阈值的三分之一开始限制,逐渐放开,时间到达后使用限流阈值进行流量控制
    在这里插入图片描述

2、降级

限流控制了服务器的最大负载,而降级是对服务器的一种保护,如果触发了某种异常,则对自身进行降级处理。
SpringBoot整合Sentinel实现服务限流、熔断_第11张图片

此图中:RT为服务的调用时间

举个例子:我对“/test”资源设置了降级规则,统计时长1000ms,熔断时长1s,比例阈值0.7,最小请求数5,最大RT为200ms。此时如果服务器1000ms内接收到的请求超过5次,并且有4次调用时间超过200ms,则触发降级,1s内对服务器进行熔断,这1s内该资源无法被访问。

在这里插入图片描述
在这里插入图片描述
异常比例与异常数大同小异,如果服务器返回异常达到阈值,则触发降级保护,服务器熔断!

注意:降级触发是对服务器得以重保护,需要同时满足两个条件:请求数超过最小请求数,慢调用比例/异常比例/异常数达到阈值,如果其一不满足,则无法触发降级

3、热点规则

如果要做到访问资源时,如果带有某参数则进行限流,不带有某参数则不限制,可以使用热点规则!

SpringBoot整合Sentinel实现服务限流、熔断_第12张图片
在这里插入图片描述
此处注意:热点规则限流绑定的是Controller方法中的参数列表,参数索引为0,代表该controller中的p1参数,如果请求时携带该参数(/test?p1=1)则会触发限流保护,如果不携带,则限流保护不会生效!

特别注意:此处必须使用@SentinelResource("")注解并绑定资源ID,直接对URL进行热点限流,限流不生效!

参数例外项

SpringBoot整合Sentinel实现服务限流、熔断_第13张图片
对热点资源限流后,如果该参数下有特殊值需要而外进行限流,可以使用参数例外项!

比如:此时如果p1=1或2,则限流QPS为100次,不会再受上方QPS为1的限流影响。

4、系统自适应限流

上方所有知识都是对特定资源限流,而系统自适应限流相当于对整个系统整体限流!
SpringBoot整合Sentinel实现服务限流、熔断_第14张图片

  • LOAD:仅对Linux生效,当线程数大于阈值,进行限流(一般为CPU核心数*2.5)
  • RT:平均响应时间,如果平均响应时间大于阈值,则进行限流
  • 线程数:当线程数大于阈值,进行限流
  • 入口QPS:当该机器上所有流量总和大于阈值,进行限流
  • CPU使用率:当CPU使用率大于阈值,进行限流

系统自适应限流与资源限流通常搭配使用!

四、自定义异常处理

1、统一异常处理

可以对Sentinel限流进行处理,返回自定义信息,避免返回默认信息

使用@SentinelResource(“标识符”)注解

如果使用该注解,被限流则抛出异常,直接使用SpringBoot的全局异常处理即可!

import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * @author 张朝宾
 * @describe
 * @since 2021/4/21
 */
@RestControllerAdvice
public class SentinelException {

    @ExceptionHandler(BlockException.class)
    public String blockException(BlockException e)
    {
        return "未知限流!!!";
    }

    @ExceptionHandler(FlowException.class)
    public String flowException(FlowException e)
    {
        return "服务限流!!!";
    }

    @ExceptionHandler(DegradeException.class)
    public String degradeException(DegradeException e)
    {
        return "服务熔断!!!";
    }

    @ExceptionHandler(ParamFlowException.class)
    public String paramFlowException(ParamFlowException e)
    {
        return "热点资源限流!!!";
    }
    @ExceptionHandler(SystemBlockException.class)
    public String systemBlockException(SystemBlockException e)
    {
        return "系统自适应限流!!!";
    }

    @ExceptionHandler(AuthorityException.class)
    public String authorityException(AuthorityException e)
    {
        return "没有授权!!!";
    }
}

不使用@SentinelResource(“标识符”)注解

不使用该注解,则由sentinel进行异常处理,需要定义配置文件:

package com.hsol.sentineldemo.demo.exception;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;

import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author 张朝宾
 * @describe
 * @since 2021/4/21
 */
@Component
public class SentinelException implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {

        if (e instanceof FlowException) {
            //服务限流
        } else if (e instanceof DegradeException) {
            //服务熔断
        } else if (e instanceof ParamFlowException) {
            //热点限流
        } else if (e instanceof SystemBlockException) {
            //系统自适应限流
        } else if (e instanceof AuthorityException) {
            //没有授权
        }
    }
}

2、单一资源异常处理

如果针对某个Controller进行异常处理,则需要使用@SentinelResource指定处理函数

    @GetMapping("/test")
    @SentinelResource(value = "test",blockHandler = "testHandler")
    public String test()
    {
        return "hello";
    }
    
 	public String testHandler(BlockException e)
    {
        return "限流异常";
    }

你可能感兴趣的:(SpringBoot,SpringCloud,spring,spring,boot,分布式,java,运维)