https://github.com/alibaba/Sentinel/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8
在官方文档中,定义的Sentinel进行资源保护的几个步骤:
- 定义资源
- 定义规则
检验规则是否生效
Entry entry = null;// 务必保证 finally 会被执行try {// 资源名可使用任意有业务语义的字符串 开启资源的保护entry = SphU.entry("自定义资源名");// 被保护的业务逻辑 method// do something...} catch (BlockException ex) {// 资源访问阻止,被限流或被降级 Sentinel定义异常 流控规则,降级规则,热点参数规则。。。。 服务降级(降级规则)// 进行相应的处理操作} catch (Exception ex) {// 若需要配置降级规则,需要通过这种方式记录业务异常 RuntimeException 服务降级 mock feign:fallbackTracer.traceEntry(ex, entry);} finally {// 务必保证 exit,务必保证每个 entry 与 exit 配对if (entry != null) {entry.exit();}
Sentinel资源保护的方式
API实现引入依赖
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-core</artifactId><version>1.8.0</version></dependency>
编写测试逻辑
@RestController@Slf4jpublic class HelloController {private static final String RESOURCE_NAME = "hello";@RequestMapping(value = "/hello")public String hello() {Entry entry = null;try {// 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。entry = SphU.entry(RESOURCE_NAME);// 被保护的业务逻辑String str = "hello world";log.info("====="+str);return str;} catch (BlockException e1) {// 资源访问阻止,被限流或被降级//进行相应的处理操作log.info("block!");} catch (Exception ex) {// 若需要配置降级规则,需要通过这种方式记录业务异常Tracer.traceEntry(ex, entry);} finally {if (entry != null) {entry.exit();}}return null;}/*** 定义流控规则*/@PostConstructprivate static void initFlowRules(){List<FlowRule> rules = new ArrayList<>();FlowRule rule = new FlowRule();//设置受保护的资源rule.setResource(RESOURCE_NAME);// 设置流控规则 QPSrule.setGrade(RuleConstant.FLOW_GRADE_QPS);// 设置受保护的资源阈值// Set limit QPS to 20.rule.setCount(1);rules.add(rule);// 加载配置好的规则FlowRuleManager.loadRules(rules);}}
测试效果:
- 业务侵入性很强,需要在controller中写入非业务代码.
- 配置不灵活 若需要添加新的受保护资源 需要手动添加 init方法来添加流控规则
@SentinelResource注解实现
@SentinelResource 注解用来标识资源是否被限流、降级。
blockHandler: 定义当资源内部发生了BlockException应该进入的方法(捕获的是Sentinel定义的异常)
fallback: 定义的是资源内部发生了Throwable应该进入的方法
exceptionsToIgnore:配置fallback可以忽略的异常
源码入口:com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect
1.引入依赖
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-annotation-aspectj</artifactId><version>1.8.0</version></dependency>
2.配置切面支持
@Configurationpublic class SentinelAspectConfiguration {@Beanpublic SentinelResourceAspect sentinelResourceAspect() {return new SentinelResourceAspect();}}
3.UserController中编写测试逻辑,添加@SentinelResource,并配置blockHandler和fallback
@RequestMapping(value = "/findOrderByUserId/{id}")@SentinelResource(value = "findOrderByUserId",fallback = "fallback",fallbackClass = ExceptionUtil.class,blockHandler = "handleException",blockHandlerClass = ExceptionUtil.class)public R findOrderByUserId(@PathVariable("id") Integer id) {//ribbon实现String url = "http://mall-order/order/findOrderByUserId/"+id;R result = restTemplate.getForObject(url,R.class);if(id==4){throw new IllegalArgumentException("非法参数异常");}return result;}
4.编写ExceptionUtil,注意如果指定了class,方法必须是static方法
public class ExceptionUtil {public static R fallback(Integer id,Throwable e){return R.error(-2,"===被异常降级啦===");}public static R handleException(Integer id, BlockException e){return R.error(-2,"===被限流啦===");}}
5.流控规则设置可以通过Sentinel dashboard配置
客户端需要引入 Transport 模块来与 Sentinel 控制台进行通信
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-transport-simple-http</artifactId><version>1.8.0</version></dependency>
-Dcsp.sentinel.dashboard.server=consoleIp:port
5. 启动 Sentinel 控制台
下载控制台 jar 包并在本地启动:可以参见 此处文档
https://github.com/alibaba/Sentinel/releases
#启动控制台命令java -jar sentinel-dashboard-1.8.0.jar
用户可以通过如下参数进行配置:
-Dsentinel.dashboard.auth.username=sentinel 用于指定控制台的登录用户名为 sentinel;
-Dsentinel.dashboard.auth.password=123456 用于指定控制台的登录密码为 123456;如果省略这两个参数,默认用户和密码均为 sentinel;
-Dserver.servlet.session.timeout=7200 用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟;
java -Dserver.port=8858 -Dsentinel.dashboard.auth.username=xushu -Dsentinel.dashboard.auth.password=123456 -jar sentinel-dashboard-1.8.0.jar
为了方便快捷启动可以在桌面创建.bat文件
java -Dserver.port=8858 -Dsentinel.dashboard.auth.username=xushu -Dsentinel.dashboard.auth.password=123456 -jar D:\server\sentinel-dashboard-1.8.0.jarpause
访问http://localhost:8080/#/login ,默认用户名密码: sentinel/sentinel
6、 Spring Cloud Alibaba整合Sentinel
1.引入依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>
2.添加yml配置,为微服务设置sentinel控制台地址
添加Sentinel后,需要暴露/actuator/sentinel端点,而Springboot默认是没有暴露该端点的,所以需要设置,测试http://localhost:8800/actuator/sentinel
server:port: 8800spring:application:name: mall-user-sentinel-democloud:nacos:discovery:server-addr: 127.0.0.1:8848sentinel:transport:# 添加sentinel的控制台地址dashboard: 127.0.0.1:8080# 指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer# port: 8719
3.在sentinel控制台中设置流控规则
- 资源名: 接口的API
- 针对来源: 默认是default,当多个微服务都调用这个资源时,可以配置微服务名来对指定的微服务设置阈值
- 阈值类型: 分为QPS和线程数 假设阈值为10
- QPS类型: 只得是每秒访问接口的次数>10就进行限流
- 线程数: 为接受请求该资源分配的线程数>10就进行限流

测试: 因为QPS是1,所以1秒内多次访问会出现如下情形:
访问http://localhost:8800/actuator/sentinel, 可以查看flowRules
微服务和Sentinel Dashboard通信原理
Sentinel控制台与微服务端之间,实现了一套服务发现机制,集成了Sentinel的微服务都会将元数据传递给Sentinel控制台,架构图如下所示:
流控针对privoder 熔断降级 针对consumer
