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

熔断降级重试设计是否可以优化 #104

Closed
DawnSouther opened this issue Apr 4, 2022 · 11 comments
Closed

熔断降级重试设计是否可以优化 #104

DawnSouther opened this issue Apr 4, 2022 · 11 comments

Comments

@DawnSouther
Copy link

我研究了一下关于熔断降级重试的设计,咱们很多都是通过配置的class去帮用户去newInstance(),这个时候想通过构造函数做一些事情就很麻烦。

咱们现在是这几个功能都走的okhttp的拦截器。熔断降级暂时只支持sentinel。

有几个问题:

  1. 重试和超时的配置协同,目前来看好像是触发了熔断就不会走重试?
  2. 这几个功能的设计都放在okhttp的interceptor我倒是都可以。
    说到底retrofit只是okhttp的一个便捷入口嘛。但是sentinel的初始化类设计的感觉有点摸不到头脑。
    也许我们只要给一个具有factory功能的bean作为全局默认配置就可以?
    还有一方面是我想去集成resilience4j做熔断,这块才多想了一些。r4j在spring gateway的做法就是类似于这种,只不过他是每次都会new一个spring context。
@chentianming11
Copy link
Collaborator

chentianming11 commented Apr 17, 2022

1、sentinel的初始化类设计,实测确实没有必要,多谢老哥提醒。
2、看了你的PR,sentinel和resilience4j的配置项最好全部做到注解配置上,因为我们无法知道用户具体的使用场景,因此全部放开是最灵活的方案。
3、熔断和重试,我认为这两者的使用场景是不同的。熔断是由于服务不稳定时,触发的保护措施。重试是解决偶发问题的机制,例如一些网络抖动等。因此,触发熔断时没必要再触发重试了,不是一个场景。
4、支持resilience4j的思路是很好的。目前你的PR最重要的就是提供了这一功能支持。
5、暂时先revert了,我还要再理一下。

@chentianming11
Copy link
Collaborator

咱们很多都是通过配置的class去帮用户去newInstance(),这个时候想通过构造函数做一些事情就很麻烦。这个具体是指什么?我感觉只要我们的配置类足够丰富,是不需要用户自己去创建实际的熔断规则实例的。

@chentianming11
Copy link
Collaborator

另外,从目前来看,resilience4j和Sentinel熔断的规则存在很大差异,我目前的自己加的抽象层确实毫无用处了。这块会考虑直接实现两套机制。

@chentianming11
Copy link
Collaborator

你的DegradeRuleRegister这个设计挺好的,优秀

@DawnSouther
Copy link
Author

1、sentinel的初始化类设计,实测确实没有必要,多谢老哥提醒。
2、看了你的PR,sentinel和resilience4j的配置项最好全部做到注解配置上,因为我们无法知道用户具体的使用场景,因此全部放开是最灵活的方案。
3、熔断和重试,我认为这两者的使用场景是不同的。熔断是由于服务不稳定时,触发的保护措施。重试是解决偶发问题的机制,例如一些网络抖动等。因此,触发熔断时没必要再触发重试了,不是一个场景。
4、支持resilience4j的思路是很好的。目前你的PR最重要的就是提供了这一功能支持。
5、暂时先revert了,我还要再理一下。

对于第二点:这个确实我也在思考应该怎么暴露熔断属性的问题,我现在正在参考别的熔断设计,看看咱这个应该怎么把属性抽象出来。说实话也是因为这个东西我没想好,所以才提了个draft pull。😄

对于第三点:我也同意这个观点。所以我们也需要提醒一下用户这个类似于ribbon和hystrix的关系:如果加载了重试配置,你的超时时间设计要考虑重试时间,熔断配置要考虑重试时的异常比例/计数。

对于第五点:老哥你合的太快了,这个版本还不好用,可以先revert,有些地方的设计我还要再想一下。

咱们的newInstance()问题:我理解这是两种设计风格不同。我的习惯是使用spring机制通过接口解耦,然后根据不同的配置条件@Conditional加载不同的实现类。你这种是使用属性配置+代理用户的newInstance()过程来实现加载不同的实现。

比如说咱们com.github.lianjiatech.retrofit.spring.boot.degrade.BaseResourceNameParser,我想加一个开关来控制整个类走一个熔断资源,还是每个方法单独走一个熔断资源。

如果我是newInstance()这种模式,我就要去改源码再加一个开关配置。如果是@Conditional我可以直接在当前工程做一个bean就可以了

还有就是我担心的是以后如果有那种new出来就不可变的对象,这时候是不会给机会去set了,这时候就要求咱们要把所有的属性都枚举出来,通过配置给他传进去,要不他还得动源码。

@chentianming11
Copy link
Collaborator

newInstance()大概理解了,确实可以以这种思路去做。其实目前项目中,大多数实现是优先从Spring获取Bean,Spring没有才会采用newInstance()进行兜底的。BaseResourceNameParser这里,确实也可以做这种方式。

@chentianming11
Copy link
Collaborator

1、sentinel的初始化类设计,实测确实没有必要,多谢老哥提醒。
2、看了你的PR,sentinel和resilience4j的配置项最好全部做到注解配置上,因为我们无法知道用户具体的使用场景,因此全部放开是最灵活的方案。
3、熔断和重试,我认为这两者的使用场景是不同的。熔断是由于服务不稳定时,触发的保护措施。重试是解决偶发问题的机制,例如一些网络抖动等。因此,触发熔断时没必要再触发重试了,不是一个场景。
4、支持resilience4j的思路是很好的。目前你的PR最重要的就是提供了这一功能支持。
5、暂时先revert了,我还要再理一下。

对于第二点:这个确实我也在思考应该怎么暴露熔断属性的问题,我现在正在参考别的熔断设计,看看咱这个应该怎么把属性抽象出来。说实话也是因为这个东西我没想好,所以才提了个draft pull。😄

对于第三点:我也同意这个观点。所以我们也需要提醒一下用户这个类似于ribbon和hystrix的关系:如果加载了重试配置,你的超时时间设计要考虑重试时间,熔断配置要考虑重试时的异常比例/计数。

对于第五点:老哥你合的太快了,这个版本还不好用,可以先revert,有些地方的设计我还要再想一下。

咱们的newInstance()问题:我理解这是两种设计风格不同。我的习惯是使用spring机制通过接口解耦,然后根据不同的配置条件@Conditional加载不同的实现类。你这种是使用属性配置+代理用户的newInstance()过程来实现加载不同的实现。

比如说咱们com.github.lianjiatech.retrofit.spring.boot.degrade.BaseResourceNameParser,我想加一个开关来控制整个类走一个熔断资源,还是每个方法单独走一个熔断资源。

如果我是newInstance()这种模式,我就要去改源码再加一个开关配置。如果是@Conditional我可以直接在当前工程做一个bean就可以了

还有就是我担心的是以后如果有那种new出来就不可变的对象,这时候是不会给机会去set了,这时候就要求咱们要把所有的属性都枚举出来,通过配置给他传进去,要不他还得动源码。

这里我打算重新设计一下。支持shentinel和resilience4j,同时支持用户用很低的成本自定义的去扩展实现自己的熔断方案。

@chentianming11
Copy link
Collaborator

我想加一个开关来控制整个类走一个熔断资源,还是每个方法单独走一个熔断资源。

如果是这个想法,会不会想有些想类走一个熔断资源,另一些又是每个方法单独走一个熔断资源?确实用户有很多不同的诉求,我这里改成从Spring中获取BaseResourceNameParser实例应该就可以了。至于用户各种个性化需求,全部靠自己的BaseResourceNameParser就好了。

@DawnSouther
Copy link
Author

@chentianming11
现在我们开启全局熔断开关的时候,只会让带有@degrade注解的client或method加载熔断配置。
这样产生的问题是在微服务通讯的场景中(或多client多method的场景中),往每个method上加配置太过繁琐,参考hystix的设计,我们只需要一个全局熔断配置。
是否应该在全局开关打开的时候,所有的client都走全局熔断配置,带有@degrade注解的走自定义熔断配置;
在全局开关关闭的时候,只有带@degrade注解的走自定义熔断配置?

@DawnSouther
Copy link
Author

如果是这个想法,会不会想有些想类走一个熔断资源,另一些又是每个方法单独走一个熔断资源?确实用户有很多不同的诉求,我这里改成从Spring中获取BaseResourceNameParser实例应该就可以了。至于用户各种个性化需求,全部靠自己的BaseResourceNameParser就好了。

这个我顺手改了就ok,问题不大

@chentianming11
Copy link
Collaborator

@chentianming11 现在我们开启全局熔断开关的时候,只会让带有@degrade注解的client或method加载熔断配置。 这样产生的问题是在微服务通讯的场景中(或多client多method的场景中),往每个method上加配置太过繁琐,参考hystix的设计,我们只需要一个全局熔断配置。 是否应该在全局开关打开的时候,所有的client都走全局熔断配置,带有@degrade注解的走自定义熔断配置; 在全局开关关闭的时候,只有带@degrade注解的走自定义熔断配置?

可以的,这种确实更合适一些,感谢建议。

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