弹簧重试:创建类似于@Retryable的自定义批注



我有许多微服务,如果与数据库的连接失败,则需要重试机制。 此重试机制必须在发生 SQLException 和 HibernateException 时触发。 在@Retryable中传递适当的拦截器将起作用,但这必须合并到所有微服务中。 我们是否可以制作一个类似于@Retryable的自定义注释,例如@DatabaseRetryable,这将触发SQLException和HibernateException的重试。

此注释的用法大致如下

@DatabaseRetryable
void executeQuery()
{
//some code
}

有几种方法可以做到这一点:

  1. 使用 spring-retry 项目并将其集成到您的应用程序中。但正如你所说,这不是你想要的。此框架提供的不仅仅是对异常的简单重试,而且比乍一看要广泛得多。
  2. 使用 AOP(面向方面编程)模型和 AspectJ 等库
  3. 创建自定义注释,
  4. 在运行方法之前内省您的类,看看它是否用@CustomRetryable注释,然后运行重试方法。然而,这不是很简单,需要与您的类正确集成。这在很大程度上取决于您的应用程序设计方式等。
  5. 如果要使其尽可能简单:创建一个帮助程序类来为您执行重试。

我的建议是看看你的问题,除了这些重试之外,你还需要解决方案吗?然后去图书馆。是简单的一个/两个用例场景,然后使用实用程序类/方法方法。

一个非常粗略的例子可能是 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;
}
}

请注意,这是一个粗略的例子,只能解释我背后的想法。看看你到底需要什么,然后从那里设计。

您可以通过使用所需名称创建元注释来解决此问题:

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Retryable(
value = { SQLException.class, HibernateException.class }
)
public @interface DatabaseRetryable {
}

您可以使用此元注释作为@Retryable的直接替换。同样的约束适用 - 它只允许在一个地方配置一些常见的行为。您还可以使用它对所有相关服务使用相同的backOff

最新更新