Alibaba Sentinel的使用

202 阅读3分钟

一、下载与安装

演示版本1.8.0

1.1 下载地址

github.com/alibaba/Sen…

1.2 安装

sentinel本身是jar包的web服务,所以直接用java命令启动即可

java -jar sentinel-dashboard-1.8.0.jar

启动成功

根据启动页面,可以推测出sentinel是基于springboot开发的。

二、springboot集成sentinel

2.1 引入maven依赖

<!--   sentinel  -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>

2.2 添加配置文件

sentinel:
      transport:
        dashboard: 127.0.0.1:8080 #sentinel的默认启动端口

2.3 在controller接口添加注解

@SentinelResource(value = "", blockHandler = "", fallback = "")
  • value: sentinel对应的资源名,默认是接口名称
  • fallback: 异常处理方法名称
  • blockHandler: 限流/降级对应的方法名称 注:fallback和blockHandler的方法参数必须要与controller的方法参数相同

(1) fallback在最后一个参数后加上Throwable类型的入参,可以捕获到controller的方法发生的异常。 (2) blockHandler在最后一个参数后加上BlockException类型的入参,可以捕获到是触发了限流规则还是降级规则

    @GetMapping("method")
    @SentinelResource(value = "method", fallback = "fallback", blockHandler = "blockHandler")
    public void method(Object param) {
        // 方法体
    }

    public void fallback(Object param, Throwable e) {
        System.out.println(e);
    }

    public void blockHandler(Object param, BlockException e) {
        if (e instanceof DegradeException) {
            throw new RuntimeException("服务降级,请稍后再试");
        }
        if (e instanceof FlowException) {
            throw new RuntimeException("服务流控,请稍后再试");
        }
    }

2.4 测试sentinel

2.4.1 测试sentinel的熔断机制

    @GetMapping("method")
    @SentinelResource(value = "method", fallback = "fallback")
    public void method(Object param) {
        // 方法体
        throw new RuntimeException("测试熔断");
    }

    public void fallback(Object param, Throwable e) {
        if (e instanceof Exception) {
            System.out.println("测试熔断成功");
        }
    }

请求127.0.0.1:服务端口/method, 可以看到控制台打印测试熔断成功

2.4.1 测试sentinel的限流机制

    @GetMapping("method")
    @SentinelResource(value = "method", blockHandler = "blockHandler")
    public SimpleMessage method(Object param) {
        // 方法体
        return new SimpleMessage(200, "访问成功");
    }

    public SimpleMessage blockHandler(Object param, BlockException e) {
        if (e instanceof DegradeException) {
            return new SimpleMessage(201, "服务降级,请稍后再试");
        }
        if (e instanceof FlowException) {
            return new SimpleMessage(201, "服务流控,请稍后再试");
        }
        return new SimpleMessage(ErrorCodeEnum.NO);
    }

浏览器访问127.0.0.1:8080,看到没有任何配置信息。因为sentinel是懒加载,所以访问接口才会有资源信息。
访问127.0.0.1:服务端口/method后,再打开sentinel 可以看到访问链路,在链路的设置流控/降级规则,设置规则的资源名要和@SentinelResource配置的value相同 设置每秒QPS不能超过5个。
多线程请求

public static void main(String[] args) {
        // 1.1发送10个请求触发限流
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                String resp = HttpClient.get("http://127.0.0.1:10004/method", 3000, 3000);
                System.out.println(resp);
            }).start();
        }
        // 预期结果,5个被拦截,5个通过
    }

结果

2.4.2 测试sentinel的降级机制

10个请求内如果请求超过10 * 0.5个响应时间超过1000ms, 则触发5秒钟的降级机制

    @GetMapping("method")
    @SentinelResource(value = "method", blockHandler = "blockHandler")
    public SimpleMessage method(Object param) throws InterruptedException {
        TimeUnit.SECONDS.sleep(1000);
        // 方法体
        return new SimpleMessage(200, "访问成功");
    }

    public SimpleMessage blockHandler(Object param, BlockException e) {
        if (e instanceof DegradeException) {
            return new SimpleMessage(201, "服务降级,请稍后再试");
        }
        if (e instanceof FlowException) {
            return new SimpleMessage(201, "服务流控,请稍后再试");
        }
        return new SimpleMessage(ErrorCodeEnum.NO);
    }

测试请求

    public static void main(String[] args) throws InterruptedException {
        // 发送10个慢请求触发降级
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                String resp = HttpClient.get("http://127.0.0.1:10004/method", 3000, 3000);
            }).start();
        }
        /*
         * 再每隔一秒发送1个请求,因为降级持续时间是5秒,所以第六个请求开始接口就会恢复正常
         */
        for (int i = 0; i < 10; i++) {
            String resp = HttpClient.get("http://127.0.0.1:10004/method", 3000, 3000);
            System.out.println(resp);
            TimeUnit.SECONDS.sleep(1);
        }
        // 预期结果,5个被拦截,5个通过
    }