領先一步
VMware 提供培訓和認證,助您加速進步。
瞭解更多這是通往 GA 之路系列部落格文章的第一篇,重點介紹了 Spring 產品組合中將於今年 11 月釋出的下一個主要版本中的主要功能。
今天,我們很榮幸地宣佈 Spring Framework 7.0 中即將推出的新彈性功能:併發限制和重試支援。
對於某些任務和資源,可能需要限制併發級別。併發限制有效地保護目標資源免受過多執行緒同時訪問,類似於執行緒池或連線池達到限制時阻止訪問的效果。這種限制對於通常沒有執行緒池限制的虛擬執行緒特別有用。
對於非同步任務,可以透過 Spring Framework 的 SimpleAsyncTaskExecutor 上的 concurrencyLimit 屬性進行限制。對於同步呼叫,可以透過 Spring Framework 的 ConcurrencyThrottleInterceptor 上的 concurrencyLimit 屬性進行限制,該攔截器自 Spring Framework 1.0 起就存在,用於 AOP 框架的程式設計使用。
使用 Spring Framework 7.0,為給定方法呼叫配置併發限制變得容易得多。只需使用 @ConcurrencyLimit 註解 Spring 管理元件中的方法,並使用 @EnableResilientMethods 註解 @Configuration 類即可啟用自動限制。或者,可以將 @ConcurrencyLimit 宣告在型別級別,以將其應用於給定類層次結構中的所有代理呼叫方法,並且可以透過在上下文中定義 ConcurrencyLimitBeanPostProcessor bean 來顯式啟用 @ConcurrencyLimit。
以下示例將 sendNotification() 方法的併發限制設定為 10。
@ConcurrencyLimit(10)
public void sendNotification() {
this.jmsClient.destination("notifications").send(...);
}
您可以選擇將限制設定為 1,從而有效地鎖定對目標 bean 例項的訪問。
@ConcurrencyLimit(1) // 1 is the default, but specifying it makes it clearer
public void sendNotification() {
this.jmsClient.destination("notifications").send(...);
}
正如諺語所說:如果一開始不成功,請再試一次。
幸運的是,這有時也適用於軟體應用程式中的錯誤:某些類別的錯誤通常可以成功重試。
歷史上,Spring 社群一直依賴 Spring Retry 專案來提供各種形式的重試支援。然而,今年我們決定在 Spring Framework 本身的最低層級整合核心重試支援。這種支援自然受到了 Spring Retry 專案的啟發,但我們將其完全重新設計為 spring-core 和 spring-context 模組中一組最小的核心重試功能。
對於宣告式重試支援,您可以使用 @Retryable 註解 Spring 管理元件中的方法,並使用 @EnableResilientMethods 註解 @Configuration 類以啟用自動重試支援。或者,可以將 @Retryable 宣告在型別級別,以將其應用於給定類層次結構中的所有代理呼叫方法,並且可以透過在上下文中定義 RetryAnnotationBeanPostProcessor bean 來顯式啟用 @Retryable。
預設情況下,方法呼叫將針對丟擲的任何異常進行重試:初始失敗後最多重試 3 次,每次嘗試之間延遲 1 秒。
@Retryable
public void sendNotification() {
this.jmsClient.destination("notifications").send(...);
}
您可以選擇透過 @Retryable 中的 includes、excludes 和隱式 value 屬性來限制觸發重試的異常型別,如下所示。
@Retryable(MessageDeliveryException.class)
public void sendNotification() {
this.jmsClient.destination("notifications").send(...);
}
請注意,@Retryable(MessageDeliveryException.class) 是 @Retryable(includes = {MessageDeliveryException.class}) 的快捷方式。
以下示例演示瞭如何配置 5 次重試嘗試和帶有少量抖動的指數回退策略。
@Retryable(
includes = MessageDeliveryException.class,
maxAttempts = 5,
delay = 100,
jitter = 10,
multiplier = 2,
maxDelay = 1000)
public void sendNotification() {
this.jmsClient.destination("notifications").send(...);
}
Spring Framework 中核心重試支援的一些功能可能與您在 Spring Retry 中熟悉的功能有所不同。例如,Spring Retry 的
@Retryable註解中maxAttempts屬性的值適用於重試操作的初始呼叫以及重試嘗試;而 Spring Framework 中的maxAttempts僅適用於實際的重試嘗試。
最後但同樣重要的是,Spring Framework 中的 @Retryable 也適用於具有響應式返回型別的響應式方法,自動使用 Reactor 的重試功能修飾管道。
@Retryable(maxAttempts = 5, delay = 100)
public Mono<Void> sendNotification() {
return Mono.from(...); // This Mono will get decorated with a retry spec.
}
與 @Retryable 為單個方法指定重試語義的宣告式方法不同,RetryTemplate 提供了一個程式設計式 API,用於重試任意程式碼塊。具體來說,RetryTemplate 根據配置的 RetryPolicy 執行並可能重試 Retryable 操作。
// Implicitly uses RetryPolicy.withDefaults()
var retryTemplate = new RetryTemplate();
retryTemplate.execute(() -> jmsClient.destination("notifications").send(...));
與 @Retryable 一樣,預設情況下,Retryable 操作將針對丟擲的任何異常進行重試:初始失敗後最多重試 3 次,每次嘗試之間延遲 1 秒。如果只需要自定義重試嘗試次數,可以使用 RetryPolicy.withMaxAttempts() 工廠方法,如下所示。
var retryTemplate = new RetryTemplate(RetryPolicy.withMaxAttempts(5));
retryTemplate.execute(() -> jmsClient.destination("notifications").send(...));
如果需要縮小重試異常的型別,可以透過 includes()、excludes() 和 predicate() 構建器方法實現。
var retryPolicy = RetryPolicy.builder()
.includes(MessageDeliveryException.class)
// .excludes(...)
// .predicate(...)
.build();
var retryTemplate = new RetryTemplate(retryPolicy);
retryTemplate.execute(() -> jmsClient.destination("notifications").send(...));
與 @Retryable 一樣,您還可以完全配置 RetryPolicy – 例如,最大重試次數和指數回退策略。
var retryPolicy = RetryPolicy.builder()
.includes(MessageDeliveryException.class)
.maxAttempts(5)
.delay(Duration.ofMillis(100))
.jitter(Duration.ofMillis(10))
.multiplier(2)
.maxDelay(Duration.ofSeconds(1))
.build();
var retryTemplate = new RetryTemplate(retryPolicy);
retryTemplate.execute(() -> jmsClient.destination("notifications").send(...));
當您升級到即將釋出的各種 Spring 產品組合專案的主要版本時,您會注意到一些專案已經從 Spring Retry 支援遷移到 Spring Framework 中新的核心重試支援。有關詳細資訊,請參閱以下專案的相關 GitHub 問題和拉取請求。
我們鼓勵您在專案中嘗試這些新功能並向我們提供反饋!
有關更多詳細資訊,請查閱參考手冊的彈性功能部分以及 org.springframework.core.retry 和 org.springframework.resilience.annotation 包中的 Javadoc。