我正在尝试弹簧重试,我面临一个奇怪的问题.当我在Rest Controller中的方法上使用重试注释时,重试不起作用.但是,如果我将该方法移动到单独的服务类,它就可以工作.以下代码不起作用:
@RestController
public class HelloController {
@RequestMapping(value = "/hello")
public String hello() {
return getInfo();
}
@Retryable(RuntimeException.class)
public String getInfo() {
Random random = new Random();
int r = random.nextInt(2);
if (r == 1) {
throw new RuntimeException();
} else {
return "Success";
}
}
}
Run Code Online (Sandbox Code Playgroud)
但以下是:
@RestController
public class HelloController {
@Autowired
private SomeService service;
@RequestMapping(value = "/hello")
public String hello() {
String result = service.getInfo();
return result;
}
}
@Service
public class SomeService {
@Retryable(RuntimeException.class)
public String …Run Code Online (Sandbox Code Playgroud) 我有这个测试:
@RunWith(MockitoJUnitRunner.class)
public class myServiceTest {
@InjectMocks
myService subject;
private myService spy;
@Before
public void before() {
spy = spy(subject);
}
@Test
public void testing() {
when(spy.print2()).thenThrow(new RuntimeException()).thenThrow(new RuntimeException()).thenReturn("completed");
spy.print1();
verify(spy, times(3)).print2();
}
Run Code Online (Sandbox Code Playgroud)
然后我有:
@Service("myService")
public class myService extends myAbstractServiceClass {
public String print1() {
String temp = "";
temp = print2();
return temp;
}
@Retryable
public String print2() {
return "completed";
}
}
Run Code Online (Sandbox Code Playgroud)
然后我有这个接口(我的abstractService实现):
public interface myServiceInterface {
@Retryable(maxAttempts = 3)
String print1() throws RuntimeException;
@Retryable(maxAttempts = 3)
String …Run Code Online (Sandbox Code Playgroud) 如何Spring Retry与外部调用集成AsyncRestTemplate?如果不可能,是否有其他框架支持它?
我的用例:
public void doSomething() throws ExecutionException, InterruptedException {
ListenableFuture<ResponseEntity<String>> future = asyncRestTemplate.getForEntity("http://localhost/foo", String.class);
// do some tasks here
ResponseEntity<String> stringResponseEntity = future.get(); // <-- How do you retry just this call?
}
Run Code Online (Sandbox Code Playgroud)
您如何重试此future.get()呼叫?如果外部服务返回 404,我想避免再次调用这些任务,而只是重试外部调用?我不能只future.get()用 a换行retryTemplate.execute(),因为它实际上不会再次调用外部服务。
Spring 的 @Retryable 注释将重试 3 次(默认)并回退到 @Recovery 方法。然而@CircuitBreaker,将重试一次并在状态关闭时回退。
我想将这两者结合起来:当断路器状态为闭合时,会在回落之前重试3次(以处理瞬态错误),如果状态为打开,将直接回落。
有什么优雅的方法可以做到这一点吗?一种可能的方法是在函数内部实现重试逻辑,但我觉得这不是最好的解决方案。
下面的@Retryable 代码适用于直接调用方法的地方,但是通过@Async 注释方法调用可重试方法然后抛出异常。有什么建议 ?
这是我的服务类
@Service
public class RetryAndRecoverService {
int counter = 0;
String str = null;
@Retryable(value = {FooException.class, BarException.class}, maxAttempts = 5, backoff = @Backoff(delay = 1000, multiplier = 1))
public String retryWithException() {
System.out.println("retryWithException - "+(counter++));
String value = getMapperValue();
if(value == null){
throw new FooException();
}
return value;
}
private String getMapperValue() {
return null;
}
@Async
public String testRetry(){
return retryWithException();
}
}
Run Code Online (Sandbox Code Playgroud)
这是 Junit 测试类
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = RetryExampleApplication.class)
public class RetryTest { …Run Code Online (Sandbox Code Playgroud) 我正在使用混合 Spring-Cloud + feign + spring-retry 来帮助在客户端重试请求(都是基于 Kotlin 的后端)
我的 spring-boot conf 是这样的:
myApp:
ribbon:
OkToRetryOnAllOperations: true
retryableStatusCodes: 404, 503
Run Code Online (Sandbox Code Playgroud)
(注意:OkToRetryOnAllOperations=true 仅用于重试 POST/PUT 请求)
重试 404 和 503 HTTP 代码听起来不错,但我不知道是否有要重试的“经典”或“默认”错误代码列表。这种好的做法存在吗?
我们假设所有请求在服务器端都是幂等的(如果不是,重试可能会导致问题)。
我正在尝试使用 Springs @Retryable 使我的服务方法在失败时重试。
@Retryable(backoff = @Backoff(delay = 1000), maxAttempts = 3)
@Transactional(rollbackFor = Throwable.class)
public Something saveSomething(Something something) {
//some logic and saving
}
Run Code Online (Sandbox Code Playgroud)
问题是,在保存某物对象后出现异常。所以事务被回滚并再次调用方法。不同之处在于,something-object 的 id 不再是 null,而是它从 Hibernate 之前的保存过程中获得的值,因此在第二次尝试中,Hibernate 不会保存该对象,而是尝试更新它。由于数据库中没有条目,因此更新不执行任何操作,并且对象不会持久保存到数据库中。
认识到这一点后,我尝试将 @Retryable 的 stateful 属性设置为 true:
@Retryable(backoff = @Backoff(delay = 1000), maxAttempts = 3, stateful = true)
@Transactional(rollbackFor = Throwable.class)
public Something saveSomething(Something something) {
//some logic and saving
}
Run Code Online (Sandbox Code Playgroud)
但是使用该配置 saveSomething() 只调用一次,而 der 不是第二次尝试。
有没有人建议解决这个问题?
我是 spring 的新手,作为项目实现的一部分,我应该在调用 JPA 存储库的服务方法上添加 spring 重试。代码如下所示
@Retryable(value = {Exception.class},maxAttempts = 1,backoff = @Backoff(300))
public Page<Account> findAllAccounts(AccountSearchRequest account, Pageable pageable) {
try {
return map(accountSearchRepository.findAll(account, pageable));
}catch (Exception e){
System.out.println("SQL EXCEPTION CAUGTH!!!!!!!!!");
}
return null;
}
@Recover
public void recover(Exception e){
System.out.println("!!!!!!!!!!!Failed to get connection!!!!!!");
}
Run Code Online (Sandbox Code Playgroud)
数据库:Postgresql,
应用程序:Java Spring Boot(公开 Rest API 以获取所有帐户)
HikariPool 最大池大小 ** : **1
Hikari 连接超时 ** : **1000
JMeter 用于发送10,000 个API 请求。
问题:我能够看到SQL EXCEPTION CAUGTH!!!!!!!!! 打印,但我认为重试不起作用,因为我没有看到恢复方法的打印。我错过了什么吗?
下面是gradle依赖项
// https://mvnrepository.com/artifact/org.springframework.retry/spring-retry …Run Code Online (Sandbox Code Playgroud) 我有一个使用 Kafka binder 的 Spring Cloud Stream 项目,我正在尝试理解并最终自定义 Cloud Stream 使用的 RetryTemplate。
我没有找到很多关于它是如何工作的文档,但是我所阅读的内容使我得出以下假设:
@StreamListener都会触发 Spring Retry这些假设正确吗?
现在,在我的应用程序中,我有一个模式,其中一些消息可以立即处理,但其他消息必须推迟到以后再次尝试(使用指数退避等)。
我应该抛出异常导致 Spring Cloud Stream 在绑定层重试这些消息,还是自己实现重试并跟踪我自己的重试上下文?
如果我应该依赖 Cloud Stream 的重试设置,我应该如何自定义退避策略等?
spring-retry spring-cloud-stream spring-cloud-stream-binder-kafka
我有一个正在尝试测试的方法
@Retryable(value = {SocketTimeoutException.class},
backoff = @Backoff(delay = 10000),
maxAttempts = 4)
public String getNewString(String oldString) throws IOException{
...
}
Run Code Online (Sandbox Code Playgroud)
我已经创建了它的测试用例,如下所示:
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestStrings {
@Test(expected = SocketTimeoutException.class)
public void testGetNewString() throws IOException {
...
}
Run Code Online (Sandbox Code Playgroud)
一切运行良好,测试用例运行 4 次,延迟 10 秒。但我想更改@Retryable的属性,即对于这个特定的测试用例,maxAttempts从4到2,延迟从10s到0.5s。我想这样做,以便在运行测试用例时不应该等待很长时间,并且测试用例应该快速结束,同时还测试重试功能。
spring-retry ×10
spring ×8
java ×6
spring-boot ×4
async-await ×1
hibernate ×1
jpa ×1
junit ×1
kotlin ×1
maven ×1
mockito ×1
retrypolicy ×1
spring-async ×1