我遇到了一个@circuitbreaker没有重试的问题。
我有一个服务类(例如类UserService和方法名getUser),这个方法调用另一个spring bean(例如AppClient和execute),后者又调用远程服务(REST调用)。execute方法用spring的@circuitbreaker-retry注释。
我在rest控制器中公开了对服务方法(类UserService和方法名getUser)的调用,并使用Postman对其进行了测试。下面是发生的情况--在超时错误的情况下,它确实调用了@recover方法。但它不会重试调用远程服务三次(默认值)。
如果我通过Postman手动运行它3次,断路器状态将变为打开,并将调用重定向到@recover方法,在重置超时后,它将恢复对远程服务的调用。
另外,我用@retryable替换了@circuitbreaker,这会调用三次(默认值)。我使用的是spring-重试版本1.2.1.release和aspectjtools版本1.6.2。
为什么不使用@circuitbreaker重试?我想有两个功能断路器和重试。根据文档,@Circuitbreaker应该同时执行这两项操作。如有任何帮助,我们将不胜感激。
@Configuration
@EnableRetry
public class cfgUserApp
{
}
@RestController
public class UserController
{
@Autowired
UserService userService;
@RequestMapping(value = "/user/{userId}", method = RequestMethod.GET, headers = "Accept=application/json")
public ResponseEntity<User> getUser(@PathVariable String userId) {
return ok(userService.getUser(userId));
}
}
/* Spring Bean -- userService */
public class UserServiceImpl
implements userService
{
@Override
public User getUser( final String userId )
{
checkArgument( User != null && !User.isEmpty(), "User Id can not be null or empty." );
try
{
final HttpGet request = buildGetUserRequest( userId );
final User userResult = appClient.execute( request,
response -> createGetReservationResult( response ) );
return userResult;
}
catch ( final IOException e )
{
LOG.error( "getUser failed.", e );
throw new AppException(e.getMessage(), e);
}
}
}
public Class Appclient {
@Recover
public <T> T recover(AppException appException, final HttpUriRequest request,
final ResponseHandler<T> responseFunction )
{
System.out.println("In Recovery");
return <T>new User();
}
@CircuitBreaker( include = AppException.class, openTimeout = 5000l, resetTimeout = 10000l )
public <T> T execute( final HttpUriRequest request,
final ResponseHandler<T> responseFunction )
{
// HTTP call
}
}
这可能是一个类似的问题--当使用JDK代理时找不到注释,因为您有接口
。
将批注移动到接口,或使用
@EnableRetry(proxyTargetClass = true)
我在PR中添加了另一个commit来解决这个问题。
编辑
您似乎误解了@circuitbreaker
;它不会在内部重试;相反,它是一个有状态的重试拦截器,在超过断路器属性后进行故障转移。
我换了你的应用来做这个...
@GetMapping("/getnumber")
public int getNumber(){
return this.userService.getNumber() + this.userService.getNumber() +
this.userService.getNumber() + this.userService.getNumber();
}
然后我看到
getNumber
fallback
getNumber
fallback
getNumber
fallback
fallback
要实现(我认为)您想要的,您需要用一个重试服务包装服务,并将恢复放在那里:
@SpringBootApplication
@EnableRetry(proxyTargetClass = true)
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@RestController
class UserRestController {
private final RetryingUserService userService;
@Autowired
public UserRestController(RetryingUserService userService) {
this.userService = userService;
}
@GetMapping("/getnumber")
public int getNumber() {
return this.userService.getNumber();
}
}
@Service
class RetryingUserService {
private final UserService userService;
public RetryingUserService(UserService userService) {
this.userService = userService;
}
@Retryable
public int getNumber() {
return this.userService.getNumber();
}
@Recover
public int fallback(RuntimeException re) {
System.out.println("fallback");
return 2;
}
}
@Service
class UserService {
@CircuitBreaker(include = RuntimeException.class)
public int getNumber() {
System.out.println("getNumber");
throw new RuntimeException();
}
}
而且
getNumber
getNumber
getNumber
fallback
或者,您可能希望将重试放在断路器中,这取决于您希望的行为。
现在编译器很高兴了,所以我可以添加注释: 程序编译,运行,但是注释被完全忽略。
Spring提供的声明式的重试类库。 示例代码: @Configuration@EnableRetrypublic class Application { @Bean public Service service() { return new Service(); }}@Serviceclass Service { @Retryable(RemoteAcces
当我运行单元测试时,我希望thisFails()方法重试3次,然后我希望看到recovery logger行打印出来,但它只尝试一次,然后抛出异常。底部的输出是在我运行测试之后。 我错过了什么? 请忽略此部分,然后跳到代码。门楣匠认为我没有足够的说明来张贴。我认为这样的措辞足以让我的问题被人理解,但出于某种原因,我不允许发布这个问题,除非我写更多的东西。还有更多的东西,等等。 --Spring启动
retry 如果源 Observable 产生一个错误事件,重新对它进行订阅,希望它不会再次产生错误 retry 操作符将不会将 error 事件,传递给观察者,然而,它会从新订阅源 Observable,给这个 Observable 一个重试的机会,让它有机会不产生 error 事件。retry 总是对观察者发出 next 事件,即便源序列产生了一个 error 事件,所以这样可能会产生重复的元
retry 函数签名: retry(number: number): Observable 如果发生错误,以指定次数重试 observable 序列。 示例 示例 1: 出错的话可以重试2次 ( StackBlitz | jsBin | jsFiddle ) // RxJS v6+ import { interval, of, throwError } from 'rxjs'; import {
我试图测试使用自定义重试策略的重试模板。为了做到这一点,我使用以下示例: https://github.com/spring-projects/spring-retry/blob/master/src/test/java/org/springframework/retry/support/retrytemplatetests.java#l57 基本上,我的目标是在得到一些特定的http错误状态(例