6

聊聊因不恰当使用alibaba sentinel而踩到的坑

 3 years ago
source link: https://my.oschina.net/u/4494662/blog/5026874
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。自从hytrix 2018年进入维护状态,再到springcloud 2020.0版本hytrix被移除,就可以料想未来一段时间springcloud全家桶的熔断降级组件基本上的首选就是alibaba sentinel。

今天就来聊聊因不恰当使用alibaba sentinel,而导致熔断降级失效的一些例子。因为sentinel还在不断迭代更新中,不同版本会有一些差异,而且在版本的迭代中,有些问题可能也已经修复。

本文演示的版本使用的sentinel-dashboard是1.8.0。使用springcloud alibaba的版本为2.2.3.RELEASE

失效场景例子

1、降级不生效问题

a、原因分析

项目中使用了自定义全局异常处理,而异常数或者异常比例的统计在

com.alibaba.csp.sentinel.adapter.spring.webmvc.AbstractSentinelInterceptor.afterCompletion

这个方法执行, 自定义全局异常的处理会先于

com.alibaba.csp.sentinel.adapter.spring.webmvc.AbstractSentinelInterceptor.afterCompletion

这个方法执行执行, 因为我们在全局异常里面已经对异常进行处理,比如转换为一个对象,这样导致AbstractSentinelInterceptor.afterCompletion无法获取到异常,进而无法统计异常数或者异常比例。

b、解决方案

在官方的issue中已经有网友提出了解决思路 https://github.com/alibaba/Sentinel/issues/1281https://github.com/alibaba/Sentinel/issues/404

因为我是在查issue的之前,就通过源码跟踪,找到答案,这边说下我的实现思路。我的思路是定义一个切面,在切面的AfterThrowing进行异常统计。因为切面会在全局异常之前执行。统计的源码我是直接把sentinel统计的源拷贝过来,核心代码如下

@Aspect
@Component
@Slf4j
public class StatisticsExceptionCountAspect {

    @Autowired
    @Lazy
    private BaseWebMvcConfig baseWebMvcConfig;

    @Pointcut("execution(* com.github.lybgeek.sentinel.controller..*.*(..))")
    public void pointcut(){

    }

    @AfterThrowing(pointcut = "pointcut()",throwing = "ex")
    public void afterAfterThrowing(Throwable ex){
        log.info("statisticsExceptionCount...");
        traceException(ex);
    }

    /**
     * 统计异常
     * @param ex
     */
    private void traceException(Throwable ex) {
        Entry entry = getEntryInRequest();
        if (entry != null) {
            Tracer.traceEntry(ex, entry);
        }
    }
    protected Entry getEntryInRequest() {
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        ServletRequestAttributes attributes = (ServletRequestAttributes)requestAttributes;
        HttpServletRequest request = attributes.getRequest();
        Object entryObject = request.getAttribute(baseWebMvcConfig.getRequestAttributeName());
        return entryObject == null ? null : (Entry)entryObject;
    }
}

2、授权规则不生效问题

a、原因分析

项目中没有实现

com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser

接口,导致无法解析请求来源

b、解决方案

在项目中自定义请求来源解析器。示例代码如下

**
 * @description: 解析访问来源,用于授权规则--黑白名单。
 * 当要进行授权规则时,则必须配置RequestOriginParser,否则授权规则无法生效
 *
 **/
@Component
public class CustomRequestOriginParser implements RequestOriginParser {

    @Override
    public String parseOrigin(HttpServletRequest request) {
        String origin = request.getParameter("origin");
        if(!StringUtils.isEmpty(origin)){
            //根据接口是否携带origin参数,如果携带参数为origin=pc,
            // 且sentinel-dashbord授权规则,来源设置为pc时,则表示要对请求来源为pc,进行黑白名单配置

            return origin;
        }
        //如果没请求参数接口没有携带,则表示按ip进行黑白名单设置
        return request.getRemoteAddr();
    }
}


3、热点规则不生效问题

a、原因分析

web埋点如果以url作为资源名,规则不生效

b、解决方案

以@SentinelResource注解定义的name作为资源名

参考官方issue https://github.com/alibaba/Sentinel/issues/1734

配置热点规则配置@SentinelResource后,可能还会出现

java.lang.reflect.UndeclaredThrowableException: null

解决方法:需要在方法中添加throws BlockException或添加blockHandler来处理异常

参考官方issue

https://github.com/alibaba/Sentinel/issues/776

示例代码

    @GetMapping(value = "/paramFlowRule/{msg}")
    @ApiImplicitParams({
            @ApiImplicitParam(name="msg",defaultValue = "hello",value="信息", paramType = "path"),
    })
    @ApiOperation(value = "测试热点规则")
    @SentinelResource(value = "testParamFlowRule")
    public AjaxResult<String> testParamFlowRule(@PathVariable("msg") String msg) throws BlockException {
        System.out.println(String.format("msg : %s",msg));
        return AjaxResult.success("测试热点规则");
    }

本文主要介绍了常见使用alibaba sentinel可能遇到的问题,不得说下阿里在国内开源做的真的挺好的,大部分问题在官方issue都能找到解答

文章下方的demo链接,提供其他熔断降级例子以及基于文件持久熔断降级配置的功能例子。感兴趣的朋友可以蛮看看。

demo链接

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-sentinel


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK