文章目录

  • 一、Sentinel 概述
  • 1、Sentinel 的主要特性
  • 2、Sentinel 分为两个部分
  • 3、启动 Sentinel 控制台
  • 二、SpringCloud 生成 sentinel 客户端
  • 1、启动 Sentinel 客户端
  • 2、nacos 控制台
  • 3、Sentinel 控制台
  • 三、接入限流埋点
  • 三、模拟高并发
  • 四、URL 流控规则
  • 1、sentinel 流控测试
  • 2、自定义限流处理逻辑
  • ①、CustomUrlBlockHandler 覆盖默认处理类 DefaultBlockExceptionHandler 实现自定义限流处理逻辑
  • ②、使用 @SentinelResource 注解实现自定义限流处理逻辑
  • 3、sentinel 动态数据源配置
  • 4、限流和熔断降级同时满足
  • 5、热点参数限流
  • ①、sentinel 控制台添加热点限流规则
  • ②、测试热点参数限流
  • 6、集群限流
  • 7、黑白名单控制
  • 五、熔断降级配置
  • 1、熔断降级说明
  • 2、慢调用比例
  • 3、异常比例
  • 4、异常数
  • 六、Zuul 支持
  • 七、Gateway 支持
  • 八、Feign 支持、RestTemplate 支持
  • 九、Endpoint 信息查看


该文章主要介绍 Sentinel 概念、 springcloud 对 Sentinel 的简单使用

官方网站:https://github.com/alibaba/Sentinel/wiki/控制台

Sentinel 技术架构 sentinel chain_sentinel

一、Sentinel 概述

Sentinel 是面向云原生微服务的流量监控,熔断降级组件。能够监控并保护你的微服务。

1、Sentinel 的主要特性

Sentinel 技术架构 sentinel chain_Sentinel 技术架构_02

2、Sentinel 分为两个部分
  • 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
  • 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器
3、启动 Sentinel 控制台

控制台简介以及安装启动:https://github.com/alibaba/Sentinel/wiki/控制台

jar 启动下载地址:https://github.com/alibaba/Sentinel/releases

源码构建:使用 maven 命令 mvn clean package 构建 Sentinel 源码

启动控制台:java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

其中 -Dserver.port=8080 用于指定 Sentinel 控制台端口为 8080。Sentinel 控制台引入基本的登录功能,默认用户名和密码都是 sentinel

控制台其他可配置参数

配置项

类型

默认值

最小值

描述

auth.enabled

boolean

true

-

是否开启登录鉴权,仅用于日常测试,生产上不建议关闭

sentinel.dashboard.auth.username

String

sentinel

-

登录控制台的用户名,默认为 sentinel

sentinel.dashboard.auth.password

String

sentinel

-

登录控制台的密码,默认为 sentinel

sentinel.dashboard.app.hideAppNoMachineMillis

Integer

0

60000

是否隐藏无健康节点的应用,距离最近一次主机心跳时间的毫秒数,默认关闭

sentinel.dashboard.removeAppNoMachineMillis

Integer

0

120000

是否自动删除无健康节点的应用,距离最近一次其下节点的心跳时间毫秒数,默认关闭

sentinel.dashboard.unhealthyMachineMillis

Integer

60000

30000

主机失联判定,不可关闭

sentinel.dashboard.autoRemoveMachineMillis

Integer

0

300000

距离最近心跳时间超过指定时间是否自动删除失联节点,默认关闭

sentinel.dashboard.unhealthyMachineMillis

Integer

60000

30000

主机失联判定,不可关闭

server.servlet.session.cookie.name

String

sentinel_dashboard_cookie

-

控制台应用的 cookie 名称,可单独设置避免同一域名下 cookie 名冲突

jar 包启动命令(云服务器需要放开端口号,window cmd 换行可以使用 ^)

java -Dserver.port=28080\
 -Dcsp.sentinel.dashboard.server=localhost:28080\
 -Dproject.name=sentinel-dashboard\
 -Dauth.enabled=true\
 -Dsentinel.dashboard.auth.username=sentinel\
 -Dsentinel.dashboard.auth.password=123456\
 -Dserver.servlet.session.timeout=7200\
 -jar sentinel-dashboard-1.8.4.jar

访问:http://127.0.0.1:28080/ ⭐ 用户名:密码 🌙 sentinel:123456

Sentinel 技术架构 sentinel chain_sentinel_03

二、SpringCloud 生成 sentinel 客户端
1、启动 Sentinel 客户端

pom.xml 依赖

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

bootstrao.yaml

spring:
  cloud:
    sentinel:
      enabled: true
      transport:
        port: 8723
        dashboard: 127.0.0.1:28080
        clientIp: 127.0.0.1
      log:
        dir: I:\nacos集群\boot-30001-sentinel

启动三个 SPRING-BOOT-SERVICE-DISCOVERY-CONSUMER 服务,配置 Sentinel 客户端端口为 8721、8722、8723

2、nacos 控制台

Sentinel 技术架构 sentinel chain_sentinel_04

3、Sentinel 控制台

如果在控制台没有找到应用,调用一下进行了 Sentinel 埋点的 URL 或方法,因为 Sentinel 使用了 lazy load 策略

Sentinel 技术架构 sentinel chain_java_05

三、接入限流埋点
  • HTTP 埋点:Sentinel starter 默认为所有的 HTTP 服务提供了限流埋点,如果只想对 HTTP 服务进行限流,那么只需要引入依赖,无需修改代码。(简单说就是所有的 controller 层接口默认提供限流埋点)
  • 自定义埋点:如果需要对某个特定的方法进行限流或降级,可以通过 @SentinelResource 注解来完成限流的埋点,示例代码如下:
@SentinelResource("resource")
 public String hello() {
     return "Hello";
 }
三、模拟高并发

该方法的作用,使用定时任务每秒发送 0~100 随机个请求,其中 127.0.0.1:20004 为服务消费者,使用 OpenFeign 调用 127.0.0.1:10001、127.0.0.1:20001、127.0.0.1:30001 三个服务提供者,将每秒发送请求数保存在 count.log 文件

public static void main(String[] args) throws IOException, InterruptedException {
        String url = String.format("http://127.0.0.1:20004/hystrix/calculate?a=%s&b=%s&type=%s", 10, 5, "*");
        CloseableHttpClient client = HttpClients.createDefault();
        ExecutorService executorService = new ThreadPoolExecutor(150, 200, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
        Timer timer = new Timer();
        String path = TestQPS.class.getResource("/").getPath();
        path = path.substring(0, path.indexOf("target")) + "/log/count.log";
        BufferedWriter writer = new BufferedWriter(new FileWriter(path));
        timer.schedule(new TimerTask() {

            @SneakyThrows
            @Override
            public void run() {
                int i = new Random().nextInt(100);
                String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(System.currentTimeMillis());
                writer.write(date + ":\t" + i + "\n");
                for (int j = 0; j < i; j++) {
                    executorService.execute(() -> {
                        try {
                            CloseableHttpResponse response = client.execute(new HttpGet(url));
                            String result = EntityUtils.toString(response.getEntity()) + "\n";
                            if (response.getStatusLine().getStatusCode() == 500) {
                                writer.write(result);
                            }
                            System.out.println(result);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    });
                }
                writer.flush();
            }
        }, 10, 1000);
    }

查看 Sentinel 控制台实时监控

Sentinel 技术架构 sentinel chain_java_06

四、URL 流控规则
1、sentinel 流控测试

点击流控规则,选择 127.0.0.1:8722 客户端,点击新增流控规则,资源名填写需要限流的 URL 相对路径,单机阈值选择需要限流的阈值,点击新增进行确认

  • 如果没使用 @SentinelResource 注解,则资源名为 url 地址
  • 如果使用 @SentinelResource 注解,则资源名为 @SentinelResource 注解指定的名字

调用流控配置的资源http://127.0.0.1:20001/discovery/rule,当 QPS 超过 1 时,可以看到限流效果如下

Sentinel 技术架构 sentinel chain_nacos_07


限流默认处理类 DefaultBlockExceptionHandler

public class DefaultBlockExceptionHandler implements BlockExceptionHandler {
    public DefaultBlockExceptionHandler() {
    }

    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        response.setStatus(429);
        PrintWriter out = response.getWriter();
        out.print("Blocked by Sentinel (flow limiting)");
        out.flush();
        out.close();
    }
}
2、自定义限流处理逻辑

自定义限流处理逻辑可以有两种实现方式

  • 方式一:新增 BlockExceptionHandler 实现类覆盖默认的 CustomUrlBlockHandler
  • 方式二:使用 @SentinelResource 注解的 blockHandler 和 blockHandlerClass 两个参数指定限流处理逻辑方法
①、CustomUrlBlockHandler 覆盖默认处理类 DefaultBlockExceptionHandler 实现自定义限流处理逻辑

CustomUrlBlockHandler 实现类

@Component
public class CustomUrlBlockHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        String msg = null;
        if (e instanceof FlowException) {
            msg = "限流了,请稍后访问";
        } else if (e instanceof DegradeException) {
            msg = "降级了,返回默认数据";
        } else if (e instanceof ParamFlowException) {
            msg = "热点参数限流";
        } else if (e instanceof SystemBlockException) {
            msg = "系统规则(负载/...不满足要求)";
        } else if (e instanceof AuthorityException) {
            msg = "授权规则不通过";
        }
        // http状态码
        response.setStatus(500);
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Type", "application/json;charset=utf-8");
        response.setContentType("application/json;charset=utf-8");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("msg", msg);
        // 返回默认数据
        Map<Object, Object> map = new HashMap<>();
        map.put("username", "admin");
        map.put("address", "西安");
        jsonObject.put("mock", map);
        response.getWriter().write(jsonObject);
    }
}

Sentinel 控制台新增限流规则

Sentinel 技术架构 sentinel chain_sentinel_08


访问测试当 QPS 大于 1,触发限流规则

Sentinel 技术架构 sentinel chain_java_09

②、使用 @SentinelResource 注解实现自定义限流处理逻辑

@SentinelResource 注解参数详细解释参考:https://github.com/alibaba/Sentinel/wiki/注解支持

  • blockHandler必须有值,如果没配置,那么不执行 blockHandler,如果配置 blockHandler 也配置了blockHandlerClass,那么会从 blockHandlerClass 数组的第一个元素作为待执行的类;
  • 如果配置 blockHandler 但是没有配置 blockHandlerClass,那么取当前执行方法的类为待执行类。
  • 如果待执行类不是当前类,那么方法必须是一个静态方法,且方法名与 blockHandler 配置一致;如果待执行类的是当前类,那么方法静态或非静态方法都可以;
  • 方法的返回值必须与 SentinelResource 注解的 blockHandler 方法返回值一样;
  • 参数方面, blockHandler 方法比 SentinelResource 注解的方法的参数多一个,最后一个参数必须是 BlockException 类型,前面的参数必须与 SentinelResource 注解的方法参数完全一致。

Sentinel 技术架构 sentinel chain_限流_10

总结:简单理解上图, blockHandler 判断是否有 BlockException,没有则进入你写的控制层;handleFallback 判断进入你写控制层抛出异常时如何处理

blockHandler 处理方法在当前类

@GetMapping(value = "/json", consumes = MediaType.APPLICATION_JSON_VALUE)
    @SentinelResource(value = "json", blockHandler = "jsonHandleException")
    public String selectStudent(@RequestBody Student student) {
        return JSONObject.toJSONString(student);
    }

    public String jsonHandleException(@RequestBody Student student, BlockException ex) {
        System.out.println("Oops: " + ex.getClass().getCanonicalName());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("param", student);
        jsonObject.put("message", ex.getMessage());
        jsonObject.put("exception", ex.getClass().getCanonicalName());
        return JSONObject.toJSONString(jsonObject);
    }

blockHandler 处理方法非当前类

@RestController
@RequestMapping("/discovery")
public class DiscoveryController {
    @GetMapping(value = "/json", consumes = MediaType.APPLICATION_JSON_VALUE)
    @SentinelResource(value = "json", blockHandler = "jsonHandleException", blockHandlerClass = ExceptionUtil.class)
    public String selectStudent(@RequestBody Student student) {
        return JSONObject.toJSONString(student);
    }
}

public class ExceptionUtil {
    public static String jsonHandleException(@RequestBody Student student, BlockException ex) {
        System.out.println("Oops: " + ex.getClass().getCanonicalName());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("param", student);
        jsonObject.put("message", ex.getMessage());
        jsonObject.put("exception", ex.getClass().getCanonicalName());
        return JSONObject.toJSONString(jsonObject);
    }
}

如果说没有配置任何blockHandler处理逻辑,那么将走handleFallback逻辑。

3、sentinel 动态数据源配置

sentinel 动态数据源配置,可解决服务关闭流控规则消失,sentinel 支持如下 6 种数据持久化方式

Sentinel 技术架构 sentinel chain_Sentinel 技术架构_11


nacos 持久化, 参考:https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel

Sentinel 技术架构 sentinel chain_nacos_12


导入 nacos 数据源依赖

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

bootstrap.yaml 添加配置,参数详细解释参考上面的官方地址

spring:
  cloud:
    sentinel:
      datasource:
        ds:
          nacos:
            server-addr: 42.193.0.90:8848
            username: nacos
            password: nacos
            data-id: sentinel-127-20001
            group-id: DEFAULT_GROUP
            namespace: 2022-4-24-sentinel
            data-type: json
            rule-type: flow

nacos 添加 sentinel 限流配置

Sentinel 技术架构 sentinel chain_限流_13


配置成功重启服务限流规则依然存在,整合了Nacos做规则存储之后

  • ⭐ Sentinel 控制台中修改规则:仅存在于服务的内存中,不会修改 Nacos 中的配置值,服务重启后恢复 Nacos 中配置。
  • ⭐ Nacos 控制台中修改规则:服务的内存中规则会更新,Nacos中持久化规则也会更新,重启后依然保持。
4、限流和熔断降级同时满足

@SentinelResource 配置 blockHandler 和 fallback

@RestController
@RequestMapping("/hystrix")
public class HystrixController {

	/*
	* 如果代码抛出 BlockException 异常则执行 ExceptionUtil 类的 calculateHandleException 方法并 return
	* 如果代码未抛出  BlockException 异常则执行 FallbackUtil 类的 calculateFallback 方法并退出
	*/
    @GetMapping("/calculate")
    @ApiAnnotation
    @SentinelResource(value = "calculate", blockHandler = "calculateHandleException",blockHandlerClass = ExceptionUtil.class,fallbackClass = FallbackUtil.class,fallback = "calculateFallback")
    public JSONObject calculate(String a, String b, String type) {
        int result = 0;
        int num1 = Integer.parseInt(a);
        int num2 = Integer.parseInt(b);
        switch (type) {
            case "+":result = num1 + num2;break;
            case "-":result = num1 - num2;break;
            case "*":result = num1 * num2;break;
            case "/":result = num1 / num2;break;
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("result",result);
        return jsonObject;
    }
}

BlockException 异常处理逻辑

@Component
public class ExceptionUtil {
    public static JSONObject calculateHandleException(String a, String b, String type, BlockException ex) {
        JSONObject jsonObject = new JSONObject();
        String msg="";
        if (ex instanceof FlowException) {
            msg = "限流了";
        } else if (ex instanceof ParamFlowException) {
            msg = "热点参数限流";
        } else if (ex instanceof DegradeException) {
            msg = "降级了";
        }
        jsonObject.put("msg", msg);
        jsonObject.put("异常处理方法", "com.ye.util.ExceptionUtil.calculateHandleException()");
        jsonObject.put("exception", ex.getClass().getCanonicalName());
        return jsonObject;
    }
}

calculateFallback 处理逻辑

public class FallbackUtil {
    public static JSONObject calculateFallback(String a, String b, String type, Throwable throwable) {

        JSONObject jsonObject = new JSONObject();
        if (throwable instanceof ArithmeticException) {
            jsonObject.put("fallback", "运算异常,calculateFallback");
            jsonObject.put("throwable", throwable.getClass().getCanonicalName());
            jsonObject.put("message", throwable.getMessage());
        }
        return jsonObject;
    }
}

测试接口: http://127.0.0.1:20001/hystrix/calculate?a=10&b=0&type=/ 从传递参数看出 10/0 会抛出算书异常

  • QPS 等于 1 走 fallback
  • Sentinel 技术架构 sentinel chain_java_14

  • QPS 大于 1,走 blockHandler, 限流和熔断降级同时满足,优先限流
  • Sentinel 技术架构 sentinel chain_限流_15

5、热点参数限流

官方说明:https://github.com/alibaba/Sentinel/wiki/热点参数限流

何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:

  • 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
  • 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制

热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。

①、sentinel 控制台添加热点限流规则

下面配置说明:

  • 资源名: calculate 对应接口 http://127.0.0.1:10001/service/hystrix/calculate?a=10&b=5&type=/
  • 参数索引: 2 对应接口的 type 参数

当 type 为 * 或者 / 时,限流阈值为 2,其余 type 参数值限流阈值为 1

Sentinel 技术架构 sentinel chain_限流_16

代码即使上方的(4、限流和熔断降级同时满足)

②、测试热点参数限流

Sentinel 技术架构 sentinel chain_java_17

6、集群限流

集群流控的作用,针对多台机器的同一个 API 进行流控,使用 gateway + sentinel 网关限流更简单

添加集群流控

  • Cluster Server 是 127.0.0.1:8721
  • Cluster Client 127.0.0.1:87212、127.0.0.1:8723

    三个客户端分别添加流控规则,选择集群模式,单机阈值 2,单机均摊(则 QPS = 6)

    根据上面配置,如果 QPS > 6 则限流,写一个方法每秒发送随机不超过10个请求,如下,每秒超过 6个请求其他会被拒绝
7、黑白名单控制
  • 很多时候,我们需要根据调用来源来判断该次请求是否允许放行,这时候可以使用 Sentinel 的来源访问控制(黑白名单控制)的功能。
  • 来源访问控制根据资源的请求来源(origin)限制资源是否通过
  • 若配置白名单则只有请求来源位于白名单内时才可通过;
  • 若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。

规则配置

来源访问控制规则(AuthorityRule)非常简单,主要有以下配置项:

  • resource:资源名,即限流规则的作用对象。
  • limitApp:对应的黑名单/白名单,不同 origin 用 , 分隔,如 appA,appB。
  • strategy:限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式。
五、熔断降级配置
1、熔断降级说明

Sentinel 提供以下几种熔断策略

  • 慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。
  • 异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
  • 异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

熔断降级规则(DegradeRule)包含下面几个重要的属性

sentinel 熔断规则

Field

说明

默认值

资源名

resource

资源名,即规则的作用对象

熔断策略

grade

熔断策略,支持慢调用比例/异常比例/异常数策略

慢调用比例

最大 RT

count

慢调用比例模式下为慢调用临界 RT(响应超出该值计为慢调用,单位为 ms);异常比例/异常数模式下为对应的阈值

熔断时长

timeWindow

熔断时长,单位为 s( 在这段时间内发生熔断、拒绝所有请求)

统计时长

statIntervalMs

统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入)

1000 ms

比例阈值

slowRatioThreshold

范围:[0~1] ,慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入), 异常比例=发生异常的请求数÷请求总数

最小请求数

minRequestAmount

熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入)(允许通过的最小请求数,在该数量内不发生熔断)

5

2、慢调用比例

如果使用了 @SentinelResource 指定了埋点的名字,则资源名为指定的名字,否则为 servletPath(即 URL 端口号后面的地址)

接口: http://127.0.0.1:20001/hystrix/calculate?a=10&b=5&type=/,该接口使用 @SentinelResource(value = “calculate”)指定

Sentinel 技术架构 sentinel chain_限流_18

calculate 慢调用比例配置说明:统计 5000 ms 内,如果请求 /hystrix/calculate 接口(资源名对应)次数大于 1时,如果 90% 响应时长超过 1000 ms,则后续请求熔断 10 s,经过10s 熔断,如果下一个请求依然响应时长超过 1000 ms,则再熔断 10s

使用 TimeUnit.SECONDS.sleep(1) 睡眠测试或者程序打断点模拟请求超时

/hystrix/calculate 接口使用 @SentinelResource 自定义异常处理

@SentinelResource(value = "calculate", blockHandler = "calculateHandleException",blockHandlerClass = ExceptionUtil.class,fallbackClass = FallbackUtil.class,fallback = "calculateFallback")
    public JSONObject calculate(String a, String b, String type) throws InterruptedException {}

测试接口

Sentinel 技术架构 sentinel chain_sentinel_19

如果不使用 @SentinelResource 指定异常处理,并且没有覆盖默认异常处理类 DefaultBlockExceptionHandler 则返回结果:Blocked by Sentinel (flow limiting)

public class DefaultBlockExceptionHandler implements BlockExceptionHandler {
    public DefaultBlockExceptionHandler() {
    }

    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        response.setStatus(429);
        PrintWriter out = response.getWriter();
        out.print("Blocked by Sentinel (flow limiting)");
        out.flush();
        out.close();
    }
}

自定义阻塞异常处理类 DiyBlockHandler.java 覆盖默认的处理类 DefaultBlockExceptionHandler

@Component
public class DiyBlockHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        String msg = null;
        if (e instanceof FlowException) {
            msg = "限流了,请稍后访问";
        } else if (e instanceof DegradeException) {
            msg = "降级了,返回默认数据";
        } else if (e instanceof ParamFlowException) {
            msg = "热点参数限流";
        } else if (e instanceof SystemBlockException) {
            msg = "系统规则(负载/...不满足要求)";
        } else if (e instanceof AuthorityException) {
            msg = "授权规则不通过";
        }
        // http状态码
        response.setStatus(500);
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Type", "application/json;charset=utf-8");
        response.setContentType("application/json;charset=utf-8");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("msg", msg);
        // 返回默认数据
        Map<Object, Object> map = new HashMap<>();
        map.put("username", "admin");
        map.put("address", "西安");
        jsonObject.put("mock", map);
        response.getWriter().write(jsonObject);
    }
}
3、异常比例

接口: http://127.0.0.1:20001/hystrix/calculate?a=10&b=5&type=/,该接口使用 @SentinelResource(value = “calculate”)指定,该接口传递的参数会有一个算术异常

Sentinel 技术架构 sentinel chain_sentinel_20


calculate 异常比例配置说明:统计 5000 ms 内,如果请求 /hystrix/calculate 接口(资源名对应)次数大于 1时,如果超过 20% 请求抛出异常,则后续请求熔断 10 s,经过10s 熔断,如果下一个请求依然失败抛出异常,则再熔断 10s

4、异常数

接口: http://127.0.0.1:20001/hystrix/calculate?a=10&b=5&type=/,该接口使用 @SentinelResource(value = “calculate”)指定,该接口传递的参数会有一个算术异常

Sentinel 技术架构 sentinel chain_nacos_21


calculate 异常比例配置说明:统计 5000 ms 内,如果请求 /hystrix/calculate 接口(资源名对应)次数大于 2 时,如果抛出异常数大于 2,则后续请求熔断 10 s,经过10s 熔断,如果下一个请求依然失败抛出异常,则再熔断 10s

六、Zuul 支持

zuul 使用参考:https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel#Zuul 支持

七、Gateway 支持

Spring Cloud Gateway 若想跟 Sentinel Starter 配合使用,需要加上 spring-cloud-alibaba-sentinel-gateway 依赖,同时需要添加 spring-cloud-starter-gateway 依赖来让 spring-cloud-alibaba-sentinel-gateway 模块里的 Spring Cloud Gateway 自动化配置类生效:

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

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

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
  • 同时请将 spring.cloud.sentinel.filter.enabled 配置项置为 false(若在网关流控控制台上看到了 URL 资源,就是此配置项没有置为 false)。Sentinel 网关流控默认的粒度是 route 维度以及自定义 API 分组维度,默认不支持 URL 粒度。如需细化到 URL 粒度,请参考 网关流控文档 自定义 API 分组。
  • 若使用 Spring Cloud Alibaba Sentinel 数据源模块,需要注意网关流控规则数据源类型是 gw-flow,若将网关流控规则数据源指定为 flow 则不生效。

注意:网关流控规则数据源类型是 gw-flow,若将网关流控规则数据源指定为 flow 则不生效。

八、Feign 支持、RestTemplate 支持

Feign 支持、RestTemplate 支持参考官方说明:https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel

Feign 支持
Feign 服务降级是服务级别的,Sentinel 服务降级方法级别的支持细粒度

RestTemplate 支持

  • @SentinelRestTemplate 注解的属性支持限流(blockHandler, blockHandlerClass)和降级(fallback, fallbackClass)的处理。
  • blockHandler 或 fallback 属性对应的方法必须是对应 blockHandlerClass 或 fallbackClass 属性中的静态方法。
  • RestTemplate 调用被 Sentinel 熔断后,会返回 RestTemplate request block by sentinel 信息,或者也可以编写对应的方法自行处理返回信息。这里提供了 SentinelClientHttpResponse 用于构造返回信息
九、Endpoint 信息查看

Sentinel Endpoint 里暴露的信息非常有用。包括当前应用的所有规则信息、日志目录、当前实例的 IP,Sentinel Dashboard 地址,Block Page,应用与 Sentinel Dashboard 的心跳频率等等信息。

Spring Boot 应用支持通过 Endpoint 来暴露相关信息,Sentinel Starter 也支持这一点。

在使用之前需要在 Maven 中添加 spring-boot-starter-actuator依赖,并在配置中允许 Endpoints 的访问。

  • Spring Boot 1.x 中添加配置 management.security.enabled=false
  • Spring Boot 2.x 中添加配置 management.endpoints.web.exposure.include=* (yaml 文件 * 需要带引号)

Spring Boot 1.x 可以通过访问 http://127.0.0.1:20001/sentinel 来查看 Sentinel Endpoint 的信息。Spring Boot 2.x 可以通过访问 http://127.0.0.1:20001/actuator/sentinel 来访问。

Sentinel 技术架构 sentinel chain_sentinel_22