如何使用 Resilience4j 断路器装饰外部依赖的服务方法(特别是在 spring 云配置服务器上)?
How to decorate service method in external dependency with Resilience4j circuit breaker (specifically on spring cloud config server)?
如何使用 Resilience4j 断路器装饰外部库中的服务方法?具体来说,我想在 spring 云配置服务器(服务器本身,而不是客户端代码)中装饰一个方法:org.springframework.cloud.config.server.environment.EnvironmentController.labelled(...)
。它需要多个参数。我无法对其进行注释,因为它在第 3 方库中。
EnvironmentController
class 是一个 Spring @RestController
.
我在 CircuitBreaker
中看到用于装饰可调用对象、函数等的方法,但 none 似乎适用于此。 (我是 Resilience4j 的新手,所以我希望我缺少一个简单的解决方案。)
一种常见的方法(不仅针对 Resilience4j
,而且通常针对 Spring
)是使用 BeanPostProcessor
(您可以看到一个不相关的示例 here).
然后在 beanPostProcessor 中,您可以获得 EnvironmentController
的句柄并使用 Resilience4j
CicrcuitBreaking 逻辑环绕它的 implementation/method。
基本上,该方法类似于:
- 在您的
@Configuration
中使用 BeanPostProcessor
来获取完全连线的句柄 EnvironmentController
- 使用 Resilience4j 围绕您感兴趣的
EnvirommentController
方法包装您自己的 CircuitBreaker
实现
- 利润
如果这不能完全清楚图片,我可以添加一些示例代码来帮助您入门,请告诉我。请记住,这可能只是解决此问题的众多方法之一。
编辑:
一些代码(不确定它是否有效,还没有测试,spring-boot
在 MVC 映射自动配置中使用 aop
的垃圾是出了名的烦人,所以你可能必须改用方面或代理配置),可能看起来像(请记住,为了后代,我会使用 lombok 来避免所有样板文件):
@Configuration
@Slf4j
public class MyConfig {
// or however the heck you get your breaker config
private final CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom().build();
private final CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.of(circuitBreakerConfig);
private final CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("suchBreakerMuchWow");
@Bean
public CircuitBreakerAwarePostProcessor circuitBreakerAwarePostProcessor() {
return new CircuitBreakerAwarePostProcessor();
}
public class CircuitBreakerAwarePostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof EnvironmentController) {
return new CircuitBreakerFriendlyEnvironmentController((EnvironmentController) bean);
}
return bean;
}
}
private interface Exclude {
Environment labelled (String name, String profiles, String label);
}
@RequiredArgsConstructor
private class CircuitBreakerFriendlyEnvironmentController implements Exclude {
@Delegate(types = EnvironmentController.class, excludes = Exclude.class)
@NonNull private final EnvironmentController environmentController;
@Override
public Environment labelled(String name, String profiles, String label) {
return circuitBreaker.executeSupplier(() -> {
log.info("such wow");
return environmentController.labelled(name, profiles, label);
});
}
}
}
如何使用 Resilience4j 断路器装饰外部库中的服务方法?具体来说,我想在 spring 云配置服务器(服务器本身,而不是客户端代码)中装饰一个方法:org.springframework.cloud.config.server.environment.EnvironmentController.labelled(...)
。它需要多个参数。我无法对其进行注释,因为它在第 3 方库中。
EnvironmentController
class 是一个 Spring @RestController
.
我在 CircuitBreaker
中看到用于装饰可调用对象、函数等的方法,但 none 似乎适用于此。 (我是 Resilience4j 的新手,所以我希望我缺少一个简单的解决方案。)
一种常见的方法(不仅针对 Resilience4j
,而且通常针对 Spring
)是使用 BeanPostProcessor
(您可以看到一个不相关的示例 here).
然后在 beanPostProcessor 中,您可以获得 EnvironmentController
的句柄并使用 Resilience4j
CicrcuitBreaking 逻辑环绕它的 implementation/method。
基本上,该方法类似于:
- 在您的
@Configuration
中使用BeanPostProcessor
来获取完全连线的句柄EnvironmentController
- 使用 Resilience4j 围绕您感兴趣的
EnvirommentController
方法包装您自己的CircuitBreaker
实现 - 利润
如果这不能完全清楚图片,我可以添加一些示例代码来帮助您入门,请告诉我。请记住,这可能只是解决此问题的众多方法之一。
编辑:
一些代码(不确定它是否有效,还没有测试,spring-boot
在 MVC 映射自动配置中使用 aop
的垃圾是出了名的烦人,所以你可能必须改用方面或代理配置),可能看起来像(请记住,为了后代,我会使用 lombok 来避免所有样板文件):
@Configuration
@Slf4j
public class MyConfig {
// or however the heck you get your breaker config
private final CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom().build();
private final CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.of(circuitBreakerConfig);
private final CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("suchBreakerMuchWow");
@Bean
public CircuitBreakerAwarePostProcessor circuitBreakerAwarePostProcessor() {
return new CircuitBreakerAwarePostProcessor();
}
public class CircuitBreakerAwarePostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof EnvironmentController) {
return new CircuitBreakerFriendlyEnvironmentController((EnvironmentController) bean);
}
return bean;
}
}
private interface Exclude {
Environment labelled (String name, String profiles, String label);
}
@RequiredArgsConstructor
private class CircuitBreakerFriendlyEnvironmentController implements Exclude {
@Delegate(types = EnvironmentController.class, excludes = Exclude.class)
@NonNull private final EnvironmentController environmentController;
@Override
public Environment labelled(String name, String profiles, String label) {
return circuitBreaker.executeSupplier(() -> {
log.info("such wow");
return environmentController.labelled(name, profiles, label);
});
}
}
}