java 以通用方式重试方法调用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10921731/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Retrying Method calls in generic way
提问by a-sak
My Java application requires a retry logic on remote calls failures. These remote calls are:
我的 Java 应用程序需要远程调用失败的重试逻辑。这些远程调用是:
- scattered all over the application
- pertain to different Remote Service classes.
- 分散在整个应用程序中
- 属于不同的远程服务类。
Also, the retry logic may have varying retry interval and varying retry attempts.
此外,重试逻辑可能具有不同的重试间隔和不同的重试尝试。
I need a generic retry() implementation which can make appropriate method calls depending on from where it is called. Below is a simple code illustration of I am looking for. I know we can attempt to do this using java reflection, but, is there a framework or an open source available somewhere which is read-to-use?
我需要一个通用的 retry() 实现,它可以根据调用的位置进行适当的方法调用。下面是我正在寻找的简单代码说明。我知道我们可以尝试使用 java 反射来做到这一点,但是,是否有一个框架或开源可用的某个地方是可读的?
try {
ClassA objA = remoteServiceA.call(paramA1, paramA2, ...);
} catch (Exception e){
ClassA objA = (ClassA)retry(remoteService, listOfParams, ..); // generic method call
}
..
try {
ClassB objB = remoteServiceB.call(paramB1, paramB2, ...);
} catch (Exception e){
ClassA objB = (ClassB)retry(remoteService, listOfParams, ..); // generic method call
}
回答by yegor256
As already suggested, you should use AOP and Java annotations. I would recommend a read-made mechanism from jcabi-aspects(I'm a developer):
正如已经建议的那样,您应该使用 AOP 和 Java 注释。我会推荐一个来自jcabi-aspects的 read-made 机制(我是一名开发人员):
@RetryOnFailure(attempts = 3, delay = 5)
public String load(URL url) {
return url.openConnection().getContent();
}
Read also this blog post: http://www.yegor256.com/2014/08/15/retry-java-method-on-exception.html
另请阅读此博客文章:http: //www.yegor256.com/2014/08/15/retry-java-method-on-exception.html
回答by Tomasz Nurkiewicz
This is a book example of where aspectj(or aopin general) can be used, see 8.2.7 Examplein Spring documentationand 5 Reasons Java Developers Should Learn and Use AspectJ.
这是可以使用aspectj(或一般aop)的书籍示例,请参阅Spring 文档中的8.2.7 示例和Java 开发人员应该学习和使用 AspectJ 的 5 个原因。
Basically an aspect intercepts all calls to given methods (specified using annotation, naming convention, whatever) and retries.
基本上一个方面拦截对给定方法的所有调用(使用注释、命名约定等指定)并重试。
回答by Raj Pandiri
Assume you have a method, that need to retied at every 500ms and upto 5 times. Current class:
假设您有一种方法,需要每 500 毫秒重连一次,最多 5 次。 当前班级:
public class RemoteCaller{
Service serviceCaller;
public void remoteCall(String message) {
serviceCaller.updateDetails( this.message);
return null;
}
}
Modified approach:
修改方法:
public class RetriableHelper<T> implements Callable<T> {
private Callable<T> task;
private int numberOfRetries;
private int numberOfTriesLeft;
private long timeToWait;
public RetriableHelper(int numberOfRetries, long timeToWait, Callable<T> task) {
this.numberOfRetries = numberOfRetries;
numberOfTriesLeft = numberOfRetries;
this.timeToWait = timeToWait;
this.task = task;
}
public T call() throws Exception {
while (true) {
try {
return task.call();
} catch (InterruptedException e) {
throw e;
} catch (CancellationException e) {
throw e;
} catch (Exception e) {
numberOfTriesLeft--;
if (numberOfTriesLeft == 0) {
throw e;
}
Thread.sleep(timeToWait);
}
}
}
}
Backend system/remote call class:
public class RemoteCaller{
Service serviceCaller;
public void remoteCall(String message) {
class RemoteCallable implements Callable<Void> {
String message;
public RemoteCallable( String message)
{
this.message = message;
}
public Void call() throws Exception{
serviceCaller.updateDetails( this.message);
return null;
}
}
RetriableHelper<Void> retriableHelper = new RetriableHelper<Void>(5, 500, new RemoteCallable( message));
try {
retriableHelper.call();
} catch (Exception e) {
throw e;
}
}
}
回答by Vijay Kiran
enter link description hereSpring has a retry annotation which servers the purpose
在此处输入链接描述Spring 有一个重试注释,用于服务目的
Step 1: Add following dependency to your POM
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.1.5.RELEASE</version>
</dependency>
Step 2: Enabling Spring Retry
To enable Spring Retry in an application, we need to add the @EnableRetry annotation to our @Configuration class:
Ex:
@Configuration
@EnableRetry
public class AppConfig { ... }
Step 3: To add retry functionality to methods, @Retryable can be used:
Ex:
@Service
public interface MyService {
@Retryable(
value = { SQLException.class },
maxAttempts = 2,
backoff = @Backoff(delay = 5000))
void retryService(String sql) throws SQLException;
...
}
Step 4.The @Recover annotation is used to define a separate recovery method when a @Retryable method fails with a specified exception:
Ex:
@Service
public interface MyService {
...
@Recover
void recover(SQLException e, String sql);
}
See Url for more details : http://www.baeldung.com/spring-retry
回答by Abhishek Pandey
If you are using spring , then better go with Aspects.
Otherwise, below sample solution can work:
如果您使用的是 spring ,那么最好使用 Aspects 。
否则,以下示例解决方案可以工作:
public class Test
{
public static void main(String[] args) throws Exception
{
Test test = new Test();
test.toRunFirst("Hello! This is normal invocation");
runWithRetry(test, "toRunFirst", "Hello! This is First, called with retry");
runWithRetry(test, "toRunSecond", "Hello! This is Second, called with retry");
}
public void toRunFirst(String s) {
System.out.println(s);
}
public void toRunSecond(String s) {
System.out.println(s);
}
public static Object runWithRetry(Object obj, String methodName, Object... args) throws Exception
{
Class<?>[] paramClass = new Class<?>[args.length];
for(int i=0; i< args.length; i++) {
paramClass[i] = args[i].getClass();
}
Method method = obj.getClass().getDeclaredMethod(methodName, paramClass);
int retryCount = 2;
for(int i=0; i< retryCount; i++) {
try {
return method.invoke(obj, args);
}
catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
回答by Markus Mikkolainen
where do you get the services from? use a factory to Proxy the service you get from the original factory. The proxy can then implement the retry transparently. See the java Proxy/ProxyGenerators in reflection.
你从哪里得到服务?使用工厂来代理您从原始工厂获得的服务。然后代理可以透明地实现重试。请参阅反射中的 java Proxy/ProxyGenerators。