Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@SentinelDegrade注解不生效 #135

Closed
shelltea opened this issue Nov 17, 2022 · 4 comments
Closed

@SentinelDegrade注解不生效 #135

shelltea opened this issue Nov 17, 2022 · 4 comments

Comments

@shelltea
Copy link

shelltea commented Nov 17, 2022

  1. 增加Sentinel依赖和配置,启动熔断降级功能;
        <dependency>
            <groupId>com.github.lianjiatech</groupId>
            <artifactId>retrofit-spring-boot-starter</artifactId>
            <version>2.3.9</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-core</artifactId>
            <version>1.8.3</version>
        </dependency>
retrofit.degrade.degrade-type = sentinel
  1. 在接口上配置@SentinelDegrade注解,异常数超过1触发降级,如下:
@SentinelDegrade(grade = 2, count = 1)
@RetrofitClient(baseUrl = "https://api.com", connectTimeoutMs = 3000,
        fallback = ApiFallback.class, fallbackFactory = ApiFallbackFactory.class)
public interface Api {

}
  1. 在单元测试中循环调用此接口的方法,通过抛出java.net.ConnectException异常模拟调不通的情况,未触发ApiFallback中的代码,在Sentinel的${user_home}/logs/csp日志目录中发现异常未计数:

image

日志的第7个数值为异常数
image

  1. 通过分析代码发现SentinelRetrofitDegrade类中未通过Tracer对异常进行统计:
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Method method = Objects.requireNonNull(request.tag(Invocation.class)).method();
        SentinelDegrade sentinelDegrade = AnnotationExtendUtils.findMergedAnnotation(method, method.getDeclaringClass(),
                SentinelDegrade.class);
        if (!needDegrade(sentinelDegrade)) {
            return chain.proceed(request);
        }
        String resourceName = parseResourceName(method);
        Entry entry = null;
        try {
            entry = SphU.entry(resourceName, ResourceTypeConstants.COMMON_WEB, EntryType.OUT);
            return chain.proceed(request);
        } catch (BlockException e) {
            throw new RetrofitBlockException(e);
        } finally {
            if (entry != null) {
                entry.exit();
            }
        }
    }

image

  1. 在Sentinel提供的sentinel-okhttp-adapter中的代码,包含了Tracer记录的代码:
    https://github.com/alibaba/Sentinel/blob/master/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/SentinelOkHttpInterceptor.java

image

@shelltea
Copy link
Author

shelltea commented Nov 17, 2022

在对SentinelRetrofitDegrade类进行了以下修改后,可以正常记录异常数,并触发熔断:

@Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Method method = Objects.requireNonNull(request.tag(Invocation.class)).method();
        SentinelDegrade sentinelDegrade = AnnotationExtendUtils.findMergedAnnotation(method, method.getDeclaringClass(),
                SentinelDegrade.class);
        if (!needDegrade(sentinelDegrade)) {
            return chain.proceed(request);
        }
        String resourceName = parseResourceName(method);
        Entry entry = null;
        try {
            entry = SphU.entry(resourceName, ResourceTypeConstants.COMMON_WEB, EntryType.OUT);
            return chain.proceed(request);
        } catch (BlockException e) {
            throw new RetrofitBlockException(e);
        } catch (IOException | RetrofitException ex) {
            Tracer.traceEntry(ex, entry);
            throw ex;
        } finally {
            if (entry != null) {
                entry.exit();
            }
        }
    }

image

5次异常,995次拦截。

通过上述的改动,可以使@Retry@SentinelDegrade组合使用,例如:

@SentinelDegrade(grade = 2, count = 1)
@RetrofitClient(baseUrl = "https://api.com", connectTimeoutMs = 3000,
        fallback = Fallback.class, fallbackFactory = FallbackFactory.class)
public interface TexSmartApi {
    @Retry(intervalMs = 20)
    @POST("api")
    Response api(@Body Request request);
}

需要在方法调用地方对Retry Failed的RetrofitException进行捕获。

可以先进行2次重试,然后抛出Retry Failed的RetrofitException,一共进行15次请求(minRequestAmount = 5)尝试后触发降级。

@chentianming11
Copy link
Collaborator

厉害了,分析的很深入。我在SentinelRetrofitDegrade加上Tracer,再发一个版本。

@chentianming11
Copy link
Collaborator

感觉对于非BlockException,都需要trace
image

2.3.10版本已修复

@shelltea
Copy link
Author

@chentianming11 升级到了2.3.10,测试可以熔断。👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants