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包部署使用。
在这里插入图片描述
第二种就是下载源代码,自己打包使用,不过注意,sentinel-dashboard使用Maven管理整个项目,需要将整体项目全部下载打包。
在这里插入图片描述
两种方式没有区别,生成的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:
在这里插入图片描述

在这里插入图片描述

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

二、构建测试项目

1、搭建SpringBoot项目

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

在这里插入图片描述

2、导入依赖,配置地址

在项目中导入依赖:

<dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
      <version>2021.1</version>  <!--如果此处使用SpringCloudAlibaba依赖管理,则不需填写版本号-->
</dependency>

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

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中才可以显示,所以请先访问一次,再查看控制台结果:
在这里插入图片描述
在这里插入图片描述
此时就可以查看实时流量,进行流量控制!

三、流量控制规则详解

在这里插入图片描述
进入访问控制台后,点击“簇点链路”即可查看服务被访问的URL,使用左侧按钮进行流控设置!

@SentinelResource(“标识符”)注解

在这里插入图片描述
该注解用于给一个Controller设置一个唯一标识符,在设置限流熔断规则时,可以使用该标识符!
在这里插入图片描述
注意:在熔断和限流中可以直接不使用此注解,直接使用URL也可以,但注意,使用注解和不使用注解的异常处理完全不同,建议全部使用,如果不使用,则建议统一完全不使用!

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

1、限流

点击“流控”,即可进行限流设置:
在这里插入图片描述

阈值类型:

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

流控模式:

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

2、降级

限流控制了服务器的最大负载,而降级是对服务器的一种保护,如果触发了某种异常,则对自身进行降级处理。
在这里插入图片描述

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

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

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

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

3、热点规则

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

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

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

参数例外项

在这里插入图片描述
对热点资源限流后,如果该参数下有特殊值需要而外进行限流,可以使用参数例外项!

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

4、系统自适应限流

上方所有知识都是对特定资源限流,而系统自适应限流相当于对整个系统整体限流!
在这里插入图片描述

  • 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 "限流异常";
    }
  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
使用 Sentinel Core 实现限流熔断需要以下步骤: 1. 引入 Sentinel Core 依赖库 在项目中引入 Sentinel Core 的依赖库,比如在 Maven 项目中可以在 pom.xml 文件中添加以下依赖: ``` <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-core</artifactId> <version>x.y.z</version> </dependency> ``` 其中 x.y.z 表示 Sentinel Core 的版本号。 2. 配置限流规则 在应用启动时,可以通过编码方式或者配置文件的方式配置限流规则。比如可以通过以下代码配置一个 qps 为 10 的限流规则: ``` FlowRule rule = new FlowRule(); rule.setResource("your-resource-name"); rule.setGrade(RuleConstant.FLOW_GRADE_QPS); rule.setCount(10); FlowRuleManager.loadRules(Collections.singletonList(rule)); ``` 其中 "your-resource-name" 表示资源名称,可以是接口名、方法名等等。 3. 配置熔断规则 同样的,可以通过以下代码配置一个异常比率为 0.5、熔断时间为 5 秒的熔断规则: ``` DegradeRule rule = new DegradeRule(); rule.setResource("your-resource-name"); rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO); rule.setCount(0.5); rule.setTimeWindow(10); DegradeRuleManager.loadRules(Collections.singletonList(rule)); ``` 其中 "your-resource-name" 也表示资源名称。 4. 在代码中使用 Sentinel 在代码中调用受限资源时,需要使用 Sentinel 的 Entry 类包装一下。比如: ``` Entry entry = null; try { entry = SphU.entry("your-resource-name"); // 执行受限资源的代码 } catch (BlockException e) { // 处理被限流的情况 } finally { if (entry != null) { entry.exit(); } } ``` 其中 SphU.entry("your-resource-name") 表示尝试进入受限资源,如果被限流了则抛出 BlockException 异常。 5. 监控 Sentinel 控制台 启动应用后,可以在 Sentinel 控制台上查看应用的运行状况、限流熔断情况等等。需要在代码中添加以下依赖: ``` <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-extension</artifactId> <version>x.y.z</version> </dependency> ``` 其中 x.y.z 表示 Sentinel 控制台的版本号。同时,在 Sentinel 控制台上也需要配置相应的数据源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值