随着微服务的流行,服务和服务之间的稳定性变得越来越重要。 Sentinel
以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
在前面我们通过以下章节对Sentinel
有了基础的了解:
Sentinel:分布式系统的流量防卫兵 | Spring Cloud 19
Sentinel:资源与规则定义 | Spring Cloud 20
Sentinel:原理深入浅出解读 | Spring Cloud 21
Sentinel:流量控制规则定义详解 | Spring Cloud 22
Spring Boot/Cloud集成Sentinel实现流量控制 | Spring Cloud 23
Spring Boot/Cloud集成Sentinel实现流量控制 (二) | Spring Cloud 24
Spring Boot/Cloud集成Sentinel实现黑白名单(授权)控制及初始本地化规则 | Spring Cloud 25
现在开始我们正式学习Sentinel
在Spring Boot/Cloud
中的集成使用。
书接上回,在前面的章节中已经存在@SentinelResource
注解的使用示例,在本章节主要进行对以下部分讲解说明:
@SentinelResource
注解各属性说明@SentinelResource
各属性理解Sentinel
支持通过 @SentinelResource
注解定义资源并配置 blockHandler
和 fallback
函数来进行限流之后的处理。
@SentinelResource
注解方式埋点不支持private
方法。
@SentinelResource
注解是 Sentinel
提供的最重要的注解之一,它还包含了多个属性,如下:
value
:资源名称,必需项(不能为空)
entryType
:entry
类型,可选项(默认为 EntryType.OUT
)
blockHandler / blockHandlerClass
:blockHandler
对应处理 BlockException
的函数名称,可选项。
blockHandler
函数访问范围需要是 public
,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException
。
blockHandler
函数默认需要和原方法在同一个类中,若希望使用其他类的函数,则可以指定 blockHandlerClass
为对应的类的 Class
对象,注意对应的函数必需为 static
函数,否则无法解析。
fallback / fallbackClass
:fallback
函数名称,可选项,用于在抛出异常的时候提供 fallback
处理逻辑。
fallback
函数可以针对所有类型的异常(除了 exceptionsToIgnore
里面排除掉的异常类型)进行处理。fallback
函数签名和位置要求:
Throwable
类型的参数用于接收对应的异常。fallback
函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass
为对应的类的 Class
对象,注意对应的函数必需为 static
函数,否则无法解析。若 blockHandler
和 fallback
都进行了配置,因限流降级而抛出 BlockException
时只会进入 blockHandler
处理逻辑,其他则抛出异常进入fallback
处理逻辑。
若未配置 blockHandler
、fallback
和 defaultFallback
,则被限流降级时会将 BlockException
直接抛出(若方法本身未定义 throws BlockException
则会被 JVM
包装一层 UndeclaredThrowableException
)。
defaultFallback(since 1.6.0)
:默认的 fallback
函数名称,可选项,通常用于通用的 fallback
逻辑(即可以用于很多服务或方法)。
默认 fallback
函数可以针对所有类型的异常(除了 exceptionsToIgnore
里面排除掉的异常类型)进行处理。
fallback
和 defaultFallback
,则只有 fallback
会生效。defaultFallback
函数签名要求: Throwable
类型的参数用于接收对应的异常。defaultFallback
函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass
为对应的类的 Class
对象,注意对应的函数必需为 static
函数,否则无法解析。exceptionsToIgnore(since 1.6.0)
:用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback
逻辑中,而是会原样抛出。
exceptionsToTrace
:与 exceptionsToIgnore
含义相反,需计入异常统计的列表。
从
1.8.0
版本开始,defaultFallback
支持在类级别进行配置。
从
1.4.0
版本开始,注解方式定义资源支持自动统计业务异常,无需手动调用Tracer.trace(ex)
来记录业务异常。Sentinel 1.4.0
以前的版本需要自行调用Tracer.trace(ex)
来记录业务异常。
若您是通过 Spring Cloud Alibaba
接入的 Sentinel
,则无需额外进行配置即可使用 @SentinelResource
注解。
若您的应用使用了 Spring AOP
,您需要通过配置的方式将 SentinelResourceAspect
注册为一个 Spring Bean
:
@Configuration
public class SentinelAspectConfiguration {@Beanpublic SentinelResourceAspect sentinelResourceAspect() {return new SentinelResourceAspect();}
}
需要引入以下依赖:
com.alibaba.csp sentinel-annotation-aspectj x.y.z
若您的应用直接使用了 AspectJ
,那么您需要在 aop.xml
文件中引入对应的 Aspect
:
需要引入以下依赖:
com.alibaba.csp sentinel-annotation-aspectj x.y.z
package com.gm.sentinel_nacos_consumer.controller;import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.concurrent.atomic.AtomicInteger;@RestController
public class SentinelResourceDemoController {private static AtomicInteger pass = new AtomicInteger();/*** 配置blockHandler,配置流控规则,发生流控时进入blockHandler逻辑** @return*/@RequestMapping("/blockHandler")@SentinelResource(value = "blockHandler", blockHandler = "blockHandlerErr")public String blockHandler() {return "请求通过";}public String blockHandlerErr(BlockException be) {return "已被限流";}/*** 配置流控、熔断规则,发生流控或熔断时进入系统默认异常处理** @return*/@RequestMapping("/fallback")@SentinelResource(value = "fallback")public String fallback() {int i = pass.addAndGet(1);if (i % 2 == 0) {i = 1 / 0;}return "请求通过";}/*** 同时配置fallback、blockHandler,配置流控规则、熔断规则,发生流控时进入blockHandler,未发生流控而是熔断时进入fallback** @return*/@RequestMapping("/fallback2")@SentinelResource(value = "fallback2", fallback = "fallbackErr", blockHandler = "blockHandlerErr")public String fallback2() {int i = pass.addAndGet(1);if (i % 2 == 0) {i = 1 / 0;}return "请求通过";}public String fallbackErr(Throwable e) {e.printStackTrace();return "已被熔断";}/*** 同时配置fallback、defaultFallback,配置流控、熔断规则,发生熔断时进入fallback,限流时进入fallback** @return*/@RequestMapping("/fallback3")@SentinelResource(value = "fallback3", fallback = "fallbackErr", defaultFallback = "defaultFallbackErr")public String fallback3() {int i = pass.addAndGet(1);if (i % 2 == 0) {i = 1 / 0;}return "请求通过";}public String defaultFallbackErr(Throwable e) {return "默认异常处理";}/*** 配置exceptionsToIgnore,配置熔断规则,发生ArrayIndexOutOfBoundsException.class异常不计入熔断统计,* 也不会进入exceptionsToIgnoreFallbackErr,进入系统默认异常处理** @return*/@RequestMapping("/exceptionsToIgnore")@SentinelResource(value = "exceptionsToIgnore", exceptionsToIgnore = {ArrayIndexOutOfBoundsException.class},fallback = "exceptionsToIgnoreFallbackErr")public String exceptionsToIgnore() {int i = pass.addAndGet(1);if (i % 2 == 1) {int[] ints = {1, 2, 3};System.out.println(ints[10]);} else if (i % 3 == 1) {i = Integer.valueOf("s");}return "请求通过";}public String exceptionsToIgnoreFallbackErr(Throwable e) {return "已被熔断";}/*** 配置exceptionsToTrace,配置熔断规则,只有发生ArrayIndexOutOfBoundsException.class异常计入熔断统计,* 并进入exceptionsToIgnoreFallbackErr,其他异常进入系统默认处理** @return*/@RequestMapping("/exceptionsToTrace")@SentinelResource(value = "exceptionsToTrace", exceptionsToTrace = {ArrayIndexOutOfBoundsException.class},fallback = "exceptionsToTraceFallbackErr")public String exceptionsToTrace() {int i = pass.addAndGet(1);if (i % 2 == 1) {int[] ints = {1, 2, 3};System.out.println(ints[10]);} else if (i % 3 == 1) {i = Integer.valueOf("s");}return "";}public String exceptionsToTraceFallbackErr(Throwable e) {return "已被熔断";}}