Sentinel Throwing exceptions in customized slots | 自定义 Slot 中抛出自定义异常后,StatisticSlot 不会统计到

rekjcdws  于 2022-10-22  发布在  其他
关注(0)|答案(3)|浏览(255)

Type: bug report

Issue Description

某些情况下StatisticNode中记录的统计信息可能是错误的

Describe what happened (or what feature you want)

如果自定义的ProcessSlot的entry方法中抛出了一个非BlockException,那么这个异常会在CtSph#entryWithPriority 执行ProcessSlot 调用链的时候被捕获且这个异常被忽略了,业务无感知。自定义ProcessSlot的entry执行失败,导致StatisticSlot的entry方法中并没有对 资源的并发数,通过数量等做统计。而在执行entry.exist的时候,StatisticSlot的exist方法会判断当前Entry是否有记录blockError,如果没有就会记录成功信息、往返时间,以及 对资源的并发持有数做减法,从而出现了统计信息错误的情况。

Describe what you expected to happen

How to reproduce it (as minimally and precisely as possible)

1,自定义一个ProcessSlot,将其放置在最后执行。 entry方法中抛出RuntimeException
2,正常使用Sentinel, 关注 entry.exist的时候 资源的ClusterNode中的curThreadNum

@Spi(order =0)
public class CustomSlot extends AbstractLinkedProcessorSlot<DefaultNode> {
    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode param, int count, boolean prioritized, Object... args) throws Throwable {
        if (resourceWrapper.getName().contains("resourceA")) {

            throw new RuntimeException("entry custome processor slot error");
        }
        fireEntry(context, resourceWrapper, param, count, prioritized, args);
    }

    @Override
    public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
        fireExit(context, resourceWrapper, count, args);

    }
}
public static  void testBug(  ){
        Entry resourceA = null;
        try {
            resourceA = SphU.entry("resourceA");
        } catch (BlockException e) {
            e.printStackTrace();
        } catch (Throwable throwable){
           //trace
        }finally {
            if (resourceA != null) {
                try {
                    DefaultNode curNode = (DefaultNode) resourceA.getCurNode();
                    ClusterNode clusterNode = curNode.getClusterNode();
                    Field curThreadNumField = ReflectionUtils.findField(ClusterNode.class, "curThreadNum");
                    curThreadNumField.setAccessible(true);
                    LongAdder curThreadNum= (LongAdder)curThreadNumField.get(clusterNode);
                    // 多次执行 依次输出 0 ,-1 ,-2,-3,-4,-5.。。。。
                    System.out.println(curThreadNum.intValue());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                resourceA.exit();
            }
        }
    }

``

environment
jdk 1.8/ senitnel1.8.3

jv4diomz

jv4diomz1#

另外在DegradeSlot中 也会根据当前Entry对象中是否存在blockError 来决定是否 执行熔断器的 onRequestComplete方法,从而改变熔断器的 状态这个也会存在问题。

aamkag61

aamkag612#

这是否算是一种用法问题而不属于Bug呢?既然是扩展Slot那就需要统一开发规范,遵循Sentinel扩展的规则,比如只能在Slot中抛出BlockException类型的异常

zysjyyx4

zysjyyx43#

Could you please illustrate your scenario that requires throwing a non-BlockException?

相关问题