【问题标题】:How to create custom retry logic for Spring Datasource?如何为 Spring Datasource 创建自定义重试逻辑?
【发布时间】:2019-05-25 17:02:27
【问题描述】:

我正在连接到 Azure SQL 数据库,我的下一个任务是在连接失败时创建自定义重试逻辑。我希望重试逻辑在启动时(如果需要)以及在应用程序运行时出现连接故障的任何时候都运行。我做了一个测试,我从我的应用程序中删除了 IP 限制,然后导致我的应用程序出现异常(如例外)。我想在抛出异常时进行处理,以便我可以触发一个验证应用程序和服务器配置正确的作业。我正在寻找可以处理这些异常并重试数据库事务的解决方案?

数据源配置

@Bean
@Primary
public DataSource dataSource() { 
     return DataSourceBuilder
            .create()
            .username("username")
            .password("password")
            .url("jdbc:sqlserver://contoso.database.windows.net:1433;database=*********;user=******@*******;password=*****;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;")
            .driverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver")
            .build();
}

application.properties

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServerDialect
spring.jpa.show-sql=true
logging.level.org.springframework.web: ERROR
logging.level.org.hibernate: ERROR
spring.datasource.tomcat.max-wait=10000
spring.datasource.tomcat.max-active=1
spring.datasource.tomcat.test-on-borrow=true
spring.jpa.hibernate.ddl-auto=update

【问题讨论】:

    标签: spring-data-jpa spring-data azure-sql-database hikaricp spring-retry


    【解决方案1】:

    以下代码可以帮助您在 Spring Boot 上为数据源创建重试逻辑:

    package com.example.demo;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    
    import javax.sql.DataSource;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.core.Ordered;
    import org.springframework.core.annotation.Order;
    import org.springframework.jdbc.datasource.AbstractDataSource;
    import org.springframework.retry.annotation.Backoff;
    import org.springframework.retry.annotation.EnableRetry;
    import org.springframework.retry.annotation.Retryable;
    
    @SpringBootApplication
    @EnableRetry
    public class DemoApplication {
    
        @Order(Ordered.HIGHEST_PRECEDENCE)
        private class RetryableDataSourceBeanPostProcessor implements BeanPostProcessor {
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName)
                    throws BeansException {
                if (bean instanceof DataSource) {
                    bean = new RetryableDataSource((DataSource)bean);
                }
                return bean;
            }
    
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName)
                    throws BeansException {
                return bean;
            }
        }
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    
        @Bean
        public BeanPostProcessor dataSouceWrapper() {
            return new RetryableDataSourceBeanPostProcessor();
        }
    }
    
    class RetryableDataSource extends AbstractDataSource {
    
        private DataSource delegate;
    
        public RetryableDataSource(DataSource delegate) {
            this.delegate = delegate;
        }
    
        @Override
        @Retryable(maxAttempts=10, backoff=@Backoff(multiplier=2.3, maxDelay=30000))
        public Connection getConnection() throws SQLException {
            return delegate.getConnection();
        }
    
        @Override
        @Retryable(maxAttempts=10, backoff=@Backoff(multiplier=2.3, maxDelay=30000))
        public Connection getConnection(String username, String password)
                throws SQLException {
            return delegate.getConnection(username, password);
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      不确定您认为什么是自定义的,但是通过利用 mavern 项目中的 pom.xml,Spring boot 和 Aspectj 有一个开箱即用的选项,因为 spring-retry 取决于 Aspectj:

      在您的项目 pom.xml 中添加以下依赖项:

      <dependency>
          <groupId>org.springframework.retry</groupId>
          <artifactId>spring-retry</artifactId>
          <version>${version}</version>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aspects</artifactId>
          <version>${version}</version>
      </dependency>

      然后将@EnableRetry 注解添加到您的代码中:

      package com.example.springretry;
       
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.retry.annotation.EnableRetry;
       
      @EnableRetry
      @SpringBootApplication
      public class SpringRetryApplication {
       
          public static void main(String[] args) {
              SpringApplication.run(SpringRetryApplication.class, args);
          }
      }

      Spring 重试模块示例可以在这里找到:https://howtodoinjava.com/spring-boot2/spring-retry-module/

      【讨论】:

        猜你喜欢
        • 2023-02-25
        • 2019-05-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-25
        • 1970-01-01
        相关资源
        最近更新 更多