首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Resiliency4j CircuitBreaker试图在AOP中调用circuitBreaker逻辑,以实现在配置中禁用时不调用断路器。

Resiliency4j CircuitBreaker试图在AOP中调用circuitBreaker逻辑,以实现在配置中禁用时不调用断路器。
EN

Stack Overflow用户
提问于 2021-07-10 02:03:47
回答 3查看 2.1K关注 0票数 0

有条件地,我想通过设置spring.cloud.circuitbreaker.resilience4j.enabled=false来开关断路器。我的逻辑应该与断路器逻辑保持完整。

我尝试使用下面的演示示例扩展到我的需求,我试图绑定断路器调用的目标方法,基于断路器标志spring.cloud.circuitbreaker.resilience4j.enabled=trueapplication.propertytruefalse的情况下。可以有一个更简单的方法来实现这一点,帮助我,如果任何其他解决方案,除了我所尝试的。

示例: 弹簧云断路器.弹性4j示例

尝试调用愉快路径-在没有异常的情况下,可以在3秒内响应,因为在bean创建中时间限制器设置为3秒。

application.properties:

代码语言:javascript
复制
spring.cloud.circuitbreaker.resilience4j.enabled=true
spring.cloud.config.enabled=false
spring.cloud.config.import-check.enabled=false
spring.main.allow-bean-definition-overriding=true

控制器:

代码语言:javascript
复制
@GetMapping("/delay/{seconds}")
public Map delay(@PathVariable int seconds) {
   return mockService.delay(seconds);
}

MockService:

代码语言:javascript
复制
@ApplyCircuitBreaker
public Map delay(int seconds) {
    return rest.getForObject("https://httpbin.org/delay/" + seconds, Map.class);
}

Config类:

代码语言:javascript
复制
@Configuration
@ConditionalOnProperty(name = { "spring.cloud.circuitbreaker.resilience4j.enabled"}, matchIfMissing = true)
public class ResiliencyConfig {

    @Bean
    public Customizer<Resilience4JCircuitBreakerFactory> defaultCustomizer() {
        return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
            .timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(3)).build())
            .circuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
            .build());
    }
}

ApplyCircuitBreaker -自定义注释仅适用于所需方法的断路器:

代码语言:javascript
复制
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ApplyCircuitBreaker {
}

AOP: CircuitBreakerAroundAspect:

代码语言:javascript
复制
@Aspect
@Component
@ConditionalOnProperty(name = { "spring.cloud.circuitbreaker.resilience4j.enabled",
    "spring.cloud.circuitbreaker.resilience4j.reactive.enabled" }, matchIfMissing = true)
public class CircuitBreakerAroundAspect {

    @Autowired
    CircuitBreakerFactory circuitBreakerFactory;

    @Around("@annotation(com.ravibeli.circuitbreaker.aspects.ApplyCircuitBreaker)")
    public Object aroundAdvice(final ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("Arguments passed to method are: {}", Arrays.toString(joinPoint.getArgs()));
        AtomicReference<Map<String, String>> fallback = new AtomicReference<>();
        Object proceed = circuitBreakerFactory.create(joinPoint.getSignature().toString())
            .run(() -> {
                try {
                    log.info("Inside CircuitBreaker logic in Aspect");
                    return joinPoint.proceed();
                } catch (Throwable t) {
                    log.error(t.getMessage());
                }
                return null;
            }, Throwable::getMessage);
        log.info("Result from method is: {}", proceed);
        return proceed;
    }
}

My requirement: circuitBreakerFactory.create(joinPoint.getSignature().toString()) .run(() -> ....)在这一行,当目标方法抛出异常时,控制应该转到回退机制调用。由于joinPoint.proceed()抛出异常,它将不得不处理异常--所以我在这里做错了,需要建议修复这个问题以解决需求。

错误日志:

代码语言:javascript
复制
{
    "timestamp": "2021-07-10T01:33:10.558+00:00",
    "status": 500,
    "error": "Internal Server Error",
/*
* 提示:该行代码过长,系统自动注释不进行高亮。一键复制会移除系统注释 
* "trace": "java.lang.ClassCastException: class java.lang.String cannot be cast to class java.util.Map (java.lang.String and java.util.Map are in module java.base of loader 'bootstrap')\r\n\tat com.ravibeli.circuitbreaker.service.MockService$$EnhancerBySpringCGLIB$$3e293bd0.delay(<generated>)\r\n\tat com.ravibeli.circuitbreaker.controllers.DemoController.delay(DemoController.java:53)\r\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n\tat java.base/java.lang.reflect.Method.invoke(Method.java:566)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)\r\n\tat org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1063)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)\r\n\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\r\n\tat org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:655)\r\n\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:764)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:228)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)\r\n\tat org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)\r\n\tat org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)\r\n\tat org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)\r\n\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)\r\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)\r\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\r\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)\r\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)\r\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\r\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\r\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)\r\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)\r\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\r\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)\r\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1723)\r\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\r\n\tat java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)\r\n\tat java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)\r\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n\tat java.base/java.lang.Thread.run(Thread.java:834)\r\n",
*/
    "message": "class java.lang.String cannot be cast to class java.util.Map (java.lang.String and java.util.Map are in module java.base of loader 'bootstrap')",
    "path": "/delay/3"
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-07-10 16:52:40

  1. 为了动态启用断路器,您可以使用Profiles或外部化配置(首选的方法是使用Profiles,您可以搜索更多关于它们的信息)
  2. 就您方面的代码而言,它看起来和运行对我来说都很好。链接到代码。如果您能够共享到代码库的链接,以便进一步调查这个问题,那就更好了。然而,这似乎是一个小问题。
票数 1
EN

Stack Overflow用户

发布于 2021-07-10 16:50:59

你好像在问几个不同的问题。

标题似乎是在问为什么当spring.cloud.circuitbreaker.resilience4j.enabled=false时方面仍然存在

问题是你有条件

代码语言:javascript
复制
@ConditionalOnProperty(name = { "spring.cloud.circuitbreaker.resilience4j.enabled",
    "spring.cloud.circuitbreaker.resilience4j.reactive.enabled" }, matchIfMissing = true)

它只是要求财产是存在的,而不是检查它设置为什么。您还需要设置havingValue=true

尽管如此,我强烈建议不要为断路器做你自己的切分。使用Resiliancy4j提供的注释,并在那里指定回退方法。我希望这能解决你在退步时遇到的其他问题。

代码语言:javascript
复制
@Bulkhead(name = 'myService', fallbackMethod = "myFallback")
@CircuitBreaker(name = 'myService', fallbackMethod = "myFallback")
@RateLimiter(name = 'myService', fallbackMethod = "myFallback")
@TimeLimiter(name = 'myService', fallbackMethod = "myFallback")
票数 2
EN

Stack Overflow用户

发布于 2021-07-11 13:29:29

谢谢,伙计们,你们的评论,有一个简单的想法来解决这个问题。我使用自定义工厂实现解决了这个问题,以使启用/禁用功能工作。

My GitHub示例代码: 弹簧云弹性4j

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68324143

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档