微服务守护神-Sentinel-其他

引言

书接上篇 微服务守护神-Sentinel-热点-授权-系统规则,上面介绍了Sentinel热点、授权、系统规则,本篇继续来Sentinel 剩下其他操作

自定义异常返回

当触发sentinel流控规则之后, sentinel就干巴巴返回异常信息,单纯的文字输出

而当前大部分项目都是前后端分离,接口设计基本采用restful的设计风格,返回都是json格式数据,此时怎办?sentinel其实也考虑过这种情况,允许顽疾自定义异常返回。

  • FlowException 限流异常

  • DegradeException 降级异常

  • ParamFlowException 参数限流异常

  • AuthorityException 授权异常

  • SystemBlockException 系统负载异常

sentinel默认给出以上5种异常,并提供BlockExceptionHandler 接口允许用户自定义

需求:自定义流控异常返回

package cn.wolfcode.error;
@Component
public class ExceptionHandlerPage implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        response.setContentType("application/json;charset=utf-8");
        ResultData data = null;
        if (e instanceof FlowException) {
            data = new ResultData(-1, "接口被限流了");
        } else if (e instanceof DegradeException) {
            data = new ResultData(-2, "接口被降级了");
        }else if (e instanceof ParamFlowException) {
            data = new ResultData(-3, "参数限流异常");
        }else if (e instanceof AuthorityException) {
            data = new ResultData(-4, "授权异常");
        }else if (e instanceof SystemBlockException) {
            data = new ResultData(-5, "系统负载异常了...");
        }
        response.getWriter().write(JSON.toJSONString(data));
    }
}
@Data
@AllArgsConstructor//全参构造
@NoArgsConstructor//无参构造
class ResultData {
    private int code;
    private String message;
}

简单明了,直接实现BlockExceptionHandler接口,重写handle 方法即可。后续测试,触发不同类型流程跳转到不同异常,输出指定格式数据。
 

@SentinelResource注解

前面项目中所有触发流控规则之后,我们的解决方案都是抛出异常,提示信息。但是开发中没有那么简单的逻辑,很多时候多需要围绕这个异常做一些后续操作。最简单例子:当触发熔断时,要走降级方法,而不是简单抛出异常。如果想实现这种操作该怎么玩?此时就得用上sentinel提供@SentinelResource的功能了。

@SentinelResource 注解作用有2个

1>定义资源,标记资源

能将普通的方法标记成一个资源,进而可以给这个资源加上流控规则。

@Service
@Slf4j
public class TraceServiceImpl {
    @SentinelResource(value = "tranceService")
    public void tranceService(){
        log.info("调用tranceService方法");
    }
}

2>定制规则

如果说前面使用可视化控制台配置流控规则,那么使用@SentinelResource注解就可以编码方式配置规则。

@SentinelResource 注解常用属性

属性作用
value资源名称,必需项(不能为空)
entryTypeentry 类型,可选项(默认为 EntryType.OUT
blockHandler/blockHandlerClassblockHandler 对应处理 BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
fallback/fallbackClassfallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求: 1. 返回值类型必须与原函数返回值类型一致; 2.方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。 3.fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
defaultFallback默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求: 1. 返回值类型必须与原函数返回值类型一致; 2. 方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。 3. defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
exceptionsToIgnore用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。

需求:当接口调用异常时,触发降级方法

@RestController
@Slf4j
public class AnnoController {
    @RequestMapping("/anno1")
    @SentinelResource(value = "anno1",
            blockHandler="anno1BlockHandler",
            fallback = "anno1Fallback"
    )
    public String anno1(String name){
        if("dafei".equals(name)){
            throw new RuntimeException();
        }
        return "anno1";
    }
    public String anno1BlockHandler(String name,BlockException ex){
        log.error("{}", ex);
        return "接口被限流或者降级了";
    }
    //Throwable时进入的方法
    public String anno1Fallback(String name,Throwable throwable) {
        log.error("{}", throwable);
        return "接口发生异常了";
    }
}

方法/anno1 带上name=dafei,触发异常,异常出现进入anno1Fallback 逻辑, 配置流控规则,正常方法触发流控后,跳转到anno1BlockHandler 逻辑。

Feign整合Sentinel

使用@SentinelResource 确实达到熔断降级逻辑,但是编写方式有点麻烦,你可以理解为写一个接口需要配置2个方法,这种方式有点不优雅,这是引入Feign的编写方式啦。也就是说怎么使用Feign来优雅解决掉这种熔断降级的麻烦。

需求:订单调用商品接口,加上熔断降级逻辑

延用上几篇的案例

步骤1:在shop-order-server项目的配置文件中开启feign对Sentinel的支持

feign:
  sentinel:
    enabled: true

步骤2:创建容错类

@Component
public class ProductFeignService implements IProductFeginService {
    @Override
    public Product findByPid(Long pid) {
        Product product = new Product();
        product.setPid(-1L);
        product.setPname("兜底数据");
        product.setPprice(0.0);
        return product;
    }
}

步骤3:在feign接口中定义容错类

@FeignClient(name = "product-service",fallback = ProductFeignFallBack.class)
public interface IProductFeginService {
    @RequestMapping("/product/{pid}")
    public Product findByPid(@PathVariable("pid") Long pid);
}

步骤4:停止所有 商品服务,重启 shop-order 服务,访问请求,观察容错效果

 可能上面的案例并不是特别恰当,我们只是通过案例来演示Feign集成Sentinel实现降级的效果. 接下来我们具体更贴切的案例来讲解Feign降级的作用.

比如我们在购物的时候,查看商品详情页面的时候,里面包含库存信息,商品详情信息,评论信息,这个需求包含的微服务如下:

没做降级熔断前,假设评论服务宕机了,那意味用户发出查看商品请求也无法正常显示了,原因查看商品接口需要调用评论微服务,而评论微服调不通,请求失败。那页面商品就无法显示,用户自然也无法进行下单。但是对于用户来说,评论看不到并不影响购物,所以这时候我们应该对评论服务进行及时降级处理,返回一个兜底数据(空数据),这样用户的查看商品请求能正常显示,只是评论数据看不到而已,但完全不影响用户。

到这,微服务守护神-Sentinel所有逻辑就讲完了,下一篇到哪个组件了呢?且听下回讲解。

 看文字不过瘾可以切换视频版:SpringCloud Alibaba 极简入门

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浪飞yes

我对钱没兴趣~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值