前言

最近在做一个小项目,对限流有些要求,遂想到引入Sentinel来实现
下面记录一下大致步骤:

Sentinel Dashboard

先按照官方文档的要求,将Dashboard下载跑起来,可以下载jar包直接跑,或者把项目clone下来,直接跑Dashboard这个子项目
在这里插入图片描述
jar包(项目)跑起来后默认端口是8080,也可以可使用 -Dserver.port=新端口 进行设置

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
项目中引入

我是SpringBoot单体项目,先引入依赖

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

然后在项目yml文件中引入sentinel的配置

spring:
  application:
    name: screen
  cloud:
    sentinel:
      transport:
        port: 996 # 本机提供给dashboard控制台调用的端口
        dashboard: localhost:8080 # dashboard控制台的地址

创建一个测试接口

@RestController
@RequestMapping("idx")
public class IdxController {

    @GetMapping("test")
    public RestResult<String> test() {
        return RestResult.ok("调用成功");
    }

}

正常调用的话返回了成功

{"code":0,"msg":"调用成功","data":null}

然后登录sentinel控制台:localhost:8080,默认账号密码为sentinel(线上建议改掉)
在这里插入图片描述
我们访问接口后,控制台实时监控区域就可以看到刚刚的访问QPS信息,接下来我们在簇点链路中看一下访问链接,并给测试链接添加一条限流规则
在这里插入图片描述
阀值类型为QPS,单机阀值这里我们设置为1,代表每秒限定访问一次
在这里插入图片描述
点新增后我们再访问一下接口测试一下,测试后发现,如果访问间隔小于1秒,接口返回了限流信息,证明限流生效了

Blocked by Sentinel (flow limiting)

但是实际中这样返回信息不太友好,我们要返回标准的带code和msg的消息体,让和接口返回异常信息保持一致,这样我们就要用到@SentinelResource

@SentinelResource

还是刚刚的接口,我们改造一下,加上@SentinelResource注解

@GetMapping("test")
@SentinelResource(value = "test", blockHandlerClass = CommonBlockHandler.class, blockHandler = "blockHandler")
public RestResult<String> test() {
    return RestResult.ok("调用成功");
}

blockHandlerClass代表被block(阻止)时的异常处理类是什么,blockHandler代表block时的处理方法,这里我使用的是异常类的形式,看一下blockHandlerClass是怎么写的

@SuppressWarnings("unused")
public class CommonBlockHandler {

    public static RestResult<String> blockHandler(BlockException ex) {
        return RestResult.error("服务调用过于频繁");
    }
}

这里定义的返回参数类型一定要和接口定义的一致,并且要是静态方法,方法的入参也要保持一致,只不过入参里可以多一个BlockException,方便查看异常

加上注解后再频繁访问一下接口,发现按我们定义的格式返回了异常信息

重启项目后Sentinel的配置可能丢失了,需要重新访问接口后再配置一条限流规则

{"code":-1,"msg":"服务调用过于频繁","data":null}

当然,也可以不用blockHandlerClass这种形式,可以直接在接口同一个类中定义一个异常处理方法,方法也不需要是静态类型,但是当异常类过多后感觉就侵入了业务代码,并且异常处理多了后就显得很臃肿,建议用blockHandlerClass的形式

更多推荐