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
3条答案
按热度按时间jv4diomz1#
另外在DegradeSlot中 也会根据当前Entry对象中是否存在blockError 来决定是否 执行熔断器的 onRequestComplete方法,从而改变熔断器的 状态这个也会存在问题。
aamkag612#
这是否算是一种用法问题而不属于Bug呢?既然是扩展Slot那就需要统一开发规范,遵循Sentinel扩展的规则,比如只能在Slot中抛出BlockException类型的异常
zysjyyx43#
Could you please illustrate your scenario that requires throwing a non-BlockException?