文章目录
- 前言
- 一、注解埋点支持
- 二、@SentinelResource 注解
- 三、实战
- 1. 准备
- 2. 纯资源定义
- 3. 添加资源配置
 
- 四、熔断(fallback)
- 1. 业务代码
- 1.1 Controller
- 1.2 Service
- 1.3 ServiceImpl
 
- 2. 熔断配置
- 3. 熔断测试
 
- 总结
前言
上一章我们已经完成了对Sentinel的适配工作,这里来学习它的更多用法。
一、注解埋点支持
Sentinel 提供了 @SentinelResource 注解用于定义资源,并提供了 AspectJ 的扩展用于自动定义资源、处理 BlockException 等。
使用 Sentinel Annotation AspectJ Extension 的时候需要引入以下依赖:
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-annotation-aspectj</artifactId>
    <version>x.y.z</version>
</dependency>
那么为什么我们没有引入这个依赖包也能使用呢,是spring-cloud-starter-alibaba-sentinel启动器帮我们引入进来了,真香呀!
二、@SentinelResource 注解
注意:注解方式埋点不支持 private 方法。
@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。 @SentinelResource 注解包含以下属性:
- value:资源名称,必需项(不能为空)
- entryType:- entry类型,可选项(默认为- EntryType.OUT)
- blockHandler/- blockHandlerClass:- blockHandler对应处理- BlockException的函数名称,可选项。
 - blockHandler函数访问范围需要是- public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为- BlockException。
 - blockHandler函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定- blockHandlerClass为对应的类的- Class对象,注意对应的函数必需为- static函数,否则无法解析。
 - fallback:- fallback函数名称,可选项,用于在抛出异常的时候提供- fallback处理逻辑。
 - fallback函数可以针对所有类型的异常(除了- exceptionsToIgnore里面排除掉的异常类型)进行处理。- fallback函数签名和位置要求:返回值类型必须与原函数返回值类型一致;方法参数列表需要和原函数一致,或者可以额外多一个- Throwable类型的参数用于接收对应的异常。
 - fallback函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定- fallbackClass为对应的类的- Class对象,注意对应的函数必需为- static函数,否则无法解析。
 - defaultFallback(since 1.6.0):默认的- fallback函数名称,可选项,通常用于通用的- fallback逻辑(即可以用于很多服务或方法)。
 默认- fallback函数可以针对所有类型的异常(除了- exceptionsToIgnore里面排除掉的异常类型)进行处理。若同时配置了- fallback和- defaultFallback,则只有- fallback会生效。- defaultFallback函数签名要求:返回值类型必须与原函数返回值类型一致;方法参数列表需要为空,或者可以额外多一个- Throwable类型的参数用于接收对应的异常。
 - defaultFallback函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定- fallbackClass为对应的类的- Class对象,注意对应的函数必需为- static函数,否则无法解析。
 - exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入- fallback逻辑中,而是会原样抛出。
注:1.6.0 之前的版本 fallback 函数只针对降级异常(DegradeException)进行处理,不能针对业务异常进行处理。
特别地,若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。若未配置 blockHandler、fallback 和 defaultFallback,则被限流降级时会将 BlockException 直接抛出。
相信大家看到这里有点麻了,跟着我的步骤一定能学会的,follow me.
三、实战
这里我们对上章案例进一步调整,查看Sentinel注解的作用。
1. 准备
这里以流控来演示
 
 
2. 纯资源定义
@Service
public class SentinelServiceImpl implements SentinelService {
    @Override
    @SentinelResource(value = "sayHello")
    public String sayHello(String name) {
        return "Hello, " + name;
    }
}

 
3. 添加资源配置
package org.example.nacos.provider.service.impl;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import org.example.nacos.provider.service.SentinelService;
import org.springframework.stereotype.Service;
/**
 * Create by zjg on 2024/8/26
 */
@Service
public class SentinelServiceImpl implements SentinelService {
    @Override
    @SentinelResource(value = "sayHello",blockHandler = "handleException",blockHandlerClass = {SentinelServiceImpl.class})
    public String sayHello(String name) {
        return "Hello, " + name;
    }
    public static String handleException(String name, BlockException ex){
        if(ex instanceof FlowException){
            return "流量激增,服务扛不住了!";
        }
        return "服务正忙,请稍后再试!";
    }
}

 
四、熔断(fallback)
这里分开讲,是为了避免冲突,这几个参数的策略是,你全都配置上没问题,但铜锣湾只能有一个大哥,那就是山鸡!
1. 业务代码
1.1 Controller
package org.example.nacos.provider.controller;
import org.example.nacos.provider.service.SentinelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
/**
 * Create by zjg on 2024/8/26
 */
@RestController
public class SentinelController {
    @Autowired
    private SentinelService service;
    @GetMapping(value = "/hello/{name}")
    public String apiHello(@PathVariable("name") String name) {
        return service.sayHello(name);
    }
    @GetMapping(value = "/bye/{name}")
    public String apiBye(@PathVariable("name") String name) {
        return service.sayBye(name);
    }
}
1.2 Service
package org.example.nacos.provider.service;
/**
 * Create by zjg on 2024/8/26
 */
public interface SentinelService {
    public String sayHello(String name);
    public String sayBye(String name);
}
1.3 ServiceImpl
package org.example.nacos.provider.service.impl;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import org.example.nacos.provider.service.SentinelService;
import org.springframework.stereotype.Service;
import java.util.Random;
/**
 * Create by zjg on 2024/8/26
 */
@Service
public class SentinelServiceImpl implements SentinelService {
    @Override
    @SentinelResource(value = "sayHello",blockHandler = "handleException")
    public String sayHello(String name) {
        return "Hello, " + name;
    }
    public static String handleException(String name, BlockException ex){
        if(ex instanceof FlowException){
            return "流量激增,服务扛不住了!";
        }
        return "服务正忙,请稍后再试!";
    }
    @Override
    @SentinelResource(value = "sayBye",fallback = "fallback")
    public String sayBye(String name) {
        int i = new Random().nextInt(10);
        if(i%2==0){
            i=1/0;
        }
        return "Bye, " + name;
    }
    public String fallback(String name,Throwable throwable){
        System.out.println(throwable.getMessage());
        return "系统异常,请稍后重试!";
    }
}
2分之1的失败几率,非常高呦!
2. 熔断配置

 
 
3. 熔断测试

 
总结
回到顶部
注意 blockHandler 函数会在原方法被限流/降级/系统保护的时候调用,而 fallback 函数会针对所有类型的异常。



















