簡介
有時客戶端需要在 config server 無響應時進行重試,以給 config server 時間進行恢復。利用 spring 提供的重試元件,我們可以方便的配置重試機制,包括重試間隔,重試次數等。
專案原始碼
為 web 專案新增依賴
開啟客戶端重試功能需要兩個新依賴,spring-retry
和 spring-boot-starter-aop
,把如下程式碼新增到 web 專案的 pom.xml 檔案中:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
複製程式碼
然後在 bootstrap.yml 檔案中新增如下配置:
spring:
application:
name: web-client
cloud:
config:
uri: http://localhost:8888
fail-fast: true
retry:
initial-interval: 1000
max-attempts: 6
max-interval: 2000
multiplier: 1.1
複製程式碼
首先把 spring.cloud.config.fail-fast
為true,即在獲取不到遠端配置時,立即失敗,但是用下邊的配置進行重試。
spring.cloud.config.retry
所有子項均為預設值:
- initial-interval: 最初重試間隔為 1000 毫秒
- max-attempts: 最多重試 6 次
- max-interval: 最長重試間隔為 2000 毫秒
- multiplier: 每次重試失敗後,重試間隔所增加的倍數
測試
如果使用了本教程的專案,我們需要首先啟動 configserver 專案,然後再啟動 registry 專案開啟 eureka,因為 web 客戶端使用了 eureka 服務,之後關閉 configserver,然後啟動 web 專案,會看到如下 log:
2018-05-15 16:04:58.421 INFO 2663 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888
複製程式碼
重試 6 次失敗後,客戶端啟動失敗,如果中途開啟 configserver,則 web 客戶端啟動成功。
細粒度控制重試
我們可以在程式碼中實現更精細的控制重試機制,在 web 專案中建立一個新的 java 類 cn.zxuqian.configurations.RetryConfiguration
,新增如下程式碼:
package cn.zxuqian.configurations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.retry.interceptor.RetryInterceptorBuilder;
import org.springframework.retry.interceptor.RetryOperationsInterceptor;
public class RetryConfiguration {
private static Logger log = LoggerFactory.getLogger(RetryConfiguration.class);
@Bean
@ConditionalOnMissingBean(name = "configServerRetryInterceptor")
public RetryOperationsInterceptor configServerRetryInterceptor() {
log.info(String.format(
"configServerRetryInterceptor: Changing backOffOptions " +
"to initial: %s, multiplier: %s, maxInterval: %s",
1000, 1.2, 5000));
return RetryInterceptorBuilder
.stateless()
.backOffOptions(1000, 1.2, 5000)
.maxAttempts(10)
.build();
}
}
複製程式碼
這裡我們定義了configServerRetryInterceptor
方法用於 Spring Retry 使用我們自定義的重試攔截器。方法使用 RetryInterceptorBuilder
按要求建立了一個 stateless 的 RetryOperationsInterceptor
,並設定了初始重試間隔為 1000 毫秒,增加倍數為 1.2 倍,最大重試間隔為 5000 毫秒,最大重試次數為 10 次,builder 還提供了諸如配置重試機制之類的介面,有興趣的讀者可自行研究。
@ConditionalOnMissingBean 標明當 BeanFactory 中沒有名為 configServerRetryInterceptor
的 bean 時才匹配此 Bean。
最後在 src/main/resources/META-INF/
(沒有可建立此資料夾) 新建一個 spring.factories
檔案,指定我們剛建立類為啟動時的配置,以在獲取遠端配置之前生效:
org.springframework.cloud.bootstrap.BootstrapConfiguration=cn.zxuqian.configurations.RetryConfiguration
複製程式碼
測試
最後在關閉 configserver 的條件下啟動 web 專案,然後就會看到重試十次之後,專案啟動失敗。
歡迎訪問我的部落格:張旭乾的部落格