如何配置Spring Retry实现无限重试及DB连接启动重试?
Alright, let's fix this for you. You're currently limiting DB connection retries to 100 times, but want to keep retrying indefinitely when the DB is down on app startup. Here's how to adjust your Spring Retry setup properly:
1. Replace Your Retry Policy with AlwaysRetryPolicy
Your current code is likely using SimpleRetryPolicy with maxAttempts = 100 to cap retries. To enable infinite retries, swap that out for Spring Retry's built-in AlwaysRetryPolicy—this policy will keep retrying until the connection succeeds (no hard limit on attempts).
2. Configure the RetryTemplate (Java Config Example)
If you're using a RetryTemplate bean, update it to use the infinite retry policy, plus add a backoff strategy (critical to avoid overwhelming your DB or wasting CPU):
@Bean public RetryTemplate retryTemplate() { RetryTemplate retryTemplate = new RetryTemplate(); // Enable infinite retries AlwaysRetryPolicy infiniteRetryPolicy = new AlwaysRetryPolicy(); retryTemplate.setRetryPolicy(infiniteRetryPolicy); // Add a 3-second delay between retries (adjust the interval as needed) FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy(); backOffPolicy.setBackOffPeriod(3000); retryTemplate.setBackOffPolicy(backOffPolicy); return retryTemplate; }
3. Update Your DB Connection Creation Logic
Option A: Using @Retryable Annotation
If you're using annotations to handle retries, adjust your @Retryable setup in one of two ways:
- Reference your custom infinite retry policy bean:
@Retryable(retryPolicy = "retryTemplate", backoff = @Backoff(delay = 3000)) public DataSource createDbConnection() { // Your existing DB connection setup logic here DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setUrl("jdbc:mysql://your-db-host:port/db-name"); dataSource.setUsername("user"); dataSource.setPassword("pass"); // Validate the connection to trigger retry on failure try (Connection conn = dataSource.getConnection()) { log.info("DB connection established successfully!"); } return dataSource; } // Note: This @Recover method won't be hit with infinite retries (unless you add a custom stop condition) @Recover public DataSource handleConnectionFailure(SQLException ex) { log.error("This should never run with infinite retries—something unexpected happened!", ex); throw new RuntimeException("Permanent DB connection failure", ex); }
- Or set
maxAttemptstoInteger.MAX_VALUEdirectly in the annotation (a simpler alternative if you don't need a custom policy):
@Retryable(maxAttempts = Integer.MAX_VALUE, backoff = @Backoff(delay = 3000))
Option B: Using RetryTemplate.execute() Directly
If you're initializing your DataSource as a bean, wrap the connection logic in retryTemplate.execute() to enforce retries during app startup:
@Bean public DataSource dataSource(RetryTemplate retryTemplate) { return retryTemplate.execute(context -> { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setUrl("jdbc:mysql://your-db-host:port/db-name"); dataSource.setUsername("user"); dataSource.setPassword("pass"); // Test the connection to trigger retry on failure try (Connection conn = dataSource.getConnection()) { log.info("Successfully connected to DB after {} attempt(s)", context.getRetryCount() + 1); } return dataSource; }); }
4. Quick Fix for Your Current 100-Limit Code
If your existing code uses SimpleRetryPolicy like this:
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(); retryPolicy.setMaxAttempts(100); // Old 100-attempt limit
Just replace that block with:
AlwaysRetryPolicy retryPolicy = new AlwaysRetryPolicy();
Or if you're using annotations, change maxAttempts = 100 to maxAttempts = Integer.MAX_VALUE or reference your infinite retry policy bean.
内容的提问来源于stack exchange,提问作者user2695543

