Spring Framework 7.0: @ConcurrencyLimit, @Retryable và RetryTemplate
Cập nhật: 16 tháng 9, 2025
Spring Framework 7.0

Concurrency Throttling
Đối với một số tác vụ và tài nguyên nhất định, có thể cần giới hạn mức độ thực thi đồng thời. Concurrency throttling giúp bảo vệ tài nguyên đích khỏi việc bị truy cập bởi quá nhiều luồng cùng lúc, tương tự như giới hạn kích thước của thread pool hoặc connection pool vốn sẽ chặn truy cập khi đạt đến giới hạn. Việc giới hạn này đặc biệt hữu ích với Virtual Threads, nơi thường không có giới hạn thread pool sẵn có.
Với các tác vụ bất đồng bộ (asynchronous), có thể giới hạn số lượng đồng thời thông qua thuộc tính concurrencyLimit của SimpleAsyncTaskExecutor trong Spring Framework. Với các lời gọi đồng bộ (synchronous), có thể giới hạn thông qua thuộc tính concurrencyLimit của ConcurrencyThrottleInterceptor — đã có từ Spring Framework 1.0 — dùng theo kiểu lập trình với AOP framework.
Từ Spring Framework 7.0, việc cấu hình giới hạn đồng thời cho một phương thức trở nên dễ dàng hơn. Chỉ cần đánh dấu method trong Spring-managed component bằng @ConcurrencyLimit, và đánh dấu class @Configuration bằng @EnableResilientMethods để bật cơ chế throttling tự động. Ngoài ra, có thể áp dụng @ConcurrencyLimit ở cấp class để áp dụng cho tất cả các method được gọi thông qua proxy trong hệ phân cấp lớp đó. Bạn cũng có thể bật @ConcurrencyLimit bằng cách định nghĩa một bean ConcurrencyLimitBeanPostProcessor trong context.
Ví dụ sau đặt giới hạn đồng thời là 10 cho hàm sendNotification()
java
1@ConcurrencyLimit(10) 2public void sendNotification() { 3 this.jmsClient.destination("notifications").send(...); 4}
Hỗ trợ Retry
Trước đây, cộng đồng Spring thường sử dụng dự án Spring Retry để hỗ trợ thử lại. Tuy nhiên, trong năm nay, nhóm Spring đã quyết định tích hợp hỗ trợ retry lõi ngay trong Spring Framework ở mức thấp nhất. Phần hỗ trợ này được lấy cảm hứng từ Spring Retry nhưng đã được thiết kế lại tối giản trong các module spring-core và spring-context.
Sử dụng @Retryable
Để sử dụng khai báo Retry, bạn có thể đánh dấu method trong Spring-managed component bằng @Retryable và đánh dấu class @Configuration bằng @EnableResilientMethods để bật retry tự động. Tương tự như @ConcurrencyLimit, @Retryable cũng có thể khai báo ở cấp class hoặc bật thông qua bean RetryAnnotationBeanPostProcessor trong context.
Mặc định, phương thức sẽ được thử lại nếu có bất kỳ exception nào, với tối đa 3 lần thử lại, và độ trễ 1 giây giữa mỗi lần:
java
1@Retryable 2public void sendNotification() { 3 this.jmsClient.destination("notifications").send(...); 4}
Bạn có thể giới hạn loại exception cần retry thông qua includes, excludes hoặc value:
java
1@Retryable(MessageDeliveryException.class) 2public void sendNotification() { 3 this.jmsClient.destination("notifications").send(...); 4}
Ví dụ sau cấu hình 5 lần thử lại, với chiến lược back-off lũy tiến (exponential back-off) và jitter:
java
1@Retryable( 2 includes = MessageDeliveryException.class, 3 maxAttempts = 5, 4 delay = 100, 5 jitter = 10, 6 multiplier = 2, 7 maxDelay = 1000) 8public void sendNotification() { 9 this.jmsClient.destination("notifications").send(...); 10}
Một số tính năng trong retry core của Spring Framework khác với Spring Retry: Ví dụ, trong Spring Retry, maxAttempts tính cả lần gọi đầu tiên và các lần retry; trong khi ở Spring Framework, maxAttempts chỉ tính các lần retry (không tính lần đầu tiên).
Cuối cùng, @Retryable trong Spring Framework cũng hoạt động với phương thức reactive:
java
1@Retryable(maxAttempts = 5, delay = 100) 2public Mono<Void> sendNotification() { 3 return Mono.from(...); // Mono này sẽ được tự động gắn retry spec. 4}
RetryTemplate
Trái ngược với @Retryable mang tính khai báo, RetryTemplate cung cấp API lập trình để thử lại các khối mã tùy ý. Cụ thể, RetryTemplate thực thi và thử lại một Retryable operation dựa trên RetryPolicy được cấu hình.
java
1// Mặc định dùng RetryPolicy.withDefaults() 2var retryTemplate = new RetryTemplate(); 3 4retryTemplate.execute(() -> jmsClient.destination("notifications").send(...));
Bạn có thể tùy chỉnh số lần retry tối đa như sau:
java
1var retryTemplate = new RetryTemplate(RetryPolicy.withMaxAttempts(5)); 2 3retryTemplate.execute(() -> jmsClient.destination("notifications").send(...));
Bạn cũng có thể cấu hình đầy đủ với back-off lũy tiến và jitter:
java
1var retryPolicy = RetryPolicy.builder() 2 .includes(MessageDeliveryException.class) 3 .maxAttempts(5) 4 .delay(Duration.ofMillis(100)) 5 .jitter(Duration.ofMillis(10)) 6 .multiplier(2) 7 .maxDelay(Duration.ofSeconds(1)) 8 .build(); 9 10var retryTemplate = new RetryTemplate(retryPolicy); 11 12retryTemplate.execute(() -> jmsClient.destination("notifications").send(...));
Cảm ơn bạn đã đọc bài viết! Nếu bạn thấy nó hữu ích, đừng quên chia sẻ nó với bạn bè và đồng nghiệp của mình nhé. Chúc bạn một ngày làm việc hiệu quả và tràn đầy năng lượng!