如果与数据库的连接失败,我有许多微服务需要重试机制。当发生SQLException和HibernateException时,必须触发此重试机制。在@Retryable中传递一个适当的拦截器将有效,但这必须包含在所有的微服务中。我们能否制作一个类似于@可还原的自定义注释,比如,它将在SQLException和HibernateException上触发重试。
这个注释的使用大致如下
@DatabaseRetryable
void executeQuery()
{
//some code
}发布于 2018-03-15 21:34:39
这方面有几种方法:
我的建议是看看你的问题,你想要的解决方案不仅仅是这些重试吗?那就去图书馆吧。它是简单的一个/两个用例场景,然后采用实用类/方法方法。
这方面的一个非常粗略的例子可能是util类:
import java.util.logging.Level;
import java.util.logging.Logger;
public class RetryOperation {
public static void main(String args[]) {
retryOnException(() -> {throw new Exception();} , Exception.class, 4);
}
interface CustomSupplier<T> {
T get() throws Exception;
}
static <E extends Exception, T> T retryOnException(CustomSupplier<T> method, Class<E> exceptionClass, int retries) {
if (method == null) {
throw new IllegalArgumentException("Method may not be null");
}
if (exceptionClass == null) {
throw new IllegalArgumentException("Exception type needs to be provided");
}
int retryCount = 0;
T result = null;
while (retryCount < retries) {
try {
result = method.get();
} catch (Exception exception) {
if (exceptionClass.isAssignableFrom(exception.getClass()) && retryCount < retries) {
// log the exception here
retryCount++;
Logger.getLogger(RetryOperation.class.getName()).log(Level.INFO, String.format("Failed %d time to execute method retrying", retryCount));
} else {
throw exception;
}
}
}
return result;
}
}请注意,这是一个粗略的例子,应该只使用函数来解释我在背后的想法。看看你到底需要什么,然后从那里设计。
发布于 2021-03-18 13:24:10
您可以通过创建一个具有所需名称的元注释来解决这个问题:
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Retryable(
value = { SQLException.class, HibernateException.class }
)
public @interface DatabaseRetryable {
}您可以使用此元注释作为@Retryable的插入替代。同样的约束也适用--它只允许在一个地方配置一些常见的行为。您还可以使用它对所有相关服务使用相同的backOff。
https://stackoverflow.com/questions/49307334
复制相似问题