【问题标题】:Spring-Retry: Create custom annotation similar to @RetryableSpring-Retry:创建类似于@Retryable 的自定义注解
【发布时间】:2018-03-15 19:00:58
【问题描述】:

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

这个注解的用法大致如下

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

【问题讨论】:

    标签: spring-boot spring-retry


    【解决方案1】:

    有几种方法:

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

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

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

    请注意,这是一个粗略的示例,应该仅用于解释我背后的想法。看看你到底需要什么,然后从那里设计。

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-09
        • 1970-01-01
        • 2019-03-15
        • 1970-01-01
        相关资源
        最近更新 更多