Async, events, scheduling và cache
Các abstraction này làm code ngắn hơn nhưng không xóa thread, queue, transaction, delivery hay consistency semantics. Production design phải chỉ rõ ownership và failure behavior.
@Async và executor
AsyncAnnotationBeanPostProcessor tạo proxy submit method vào TaskExecutor; self-invocation không async. Return Future hoặc CompletableFuture để caller quan sát lỗi; void method cần AsyncUncaughtExceptionHandler.
| Executor concern | Yêu cầu production |
|---|---|
| Capacity | Bounded threads và queue dựa trên workload. |
| Overload | Rejection policy, backpressure hoặc load shedding rõ. |
| Observability | Tên thread, active/queued/rejected metrics và task duration. |
| Shutdown | Dừng nhận task, drain có timeout rồi hủy có kiểm soát. |
| Context | Security, MDC, locale và transaction không tự truyền đầy đủ; propagate và cleanup có chủ đích. |
Application events
ApplicationEventPublisher mặc định gọi listeners đồng bộ trên caller thread, nên listener exception có thể ảnh hưởng publisher. Async listener đổi thread và transaction semantics. @TransactionalEventListener bind với phase như AFTER_COMMIT, nhưng không bảo đảm durable delivery; process crash vẫn có thể làm mất event.
Scheduling trong một instance và cluster
@Scheduled dùng TaskScheduler: fixed rate đo giữa thời điểm start, fixed delay đo sau completion, cron phụ thuộc clock và timezone. Trong cluster, mỗi instance đều chạy job nếu không có leader election, distributed scheduler hoặc lock.
- Job phải idempotent và có concurrency/misfire policy.
- Giới hạn runtime, retries và batch size.
- Ghi last success, duration, processed/error count và lag.
- Không giữ distributed lock trong lúc gọi remote dependency quá lâu.
Cache abstraction
@Cacheable tạo key, lookup, gọi target khi miss rồi put; @CachePut luôn gọi target và cập nhật cache; @CacheEvict invalidates entries. Đây cũng là proxy advice nên self-invocation có cùng giới hạn.
Spring cache abstraction không định nghĩa TTL, serialization, eviction capacity, stampede hay distributed consistency; provider và configuration quyết định các behavior này.
Key và invalidation
Key phải gồm tenant, version và arguments ổn định; không dùng mutable object hoặc toString() không ổn định. Việc cache null và errors phải có chủ đích. Update DB rồi evict cache có race; transaction-aware cache hoặc event invalidation vẫn cần thiết kế khi event/eviction fail.
Retry và advice ordering
Spring Framework core không tự làm mọi async/cache operation resilient. Khi dùng retry library, xác định exception retryable, attempts, exponential backoff, jitter, deadline và idempotency. Không retry validation, authentication hoặc permanent failure.
Ordering với transaction thay semantics: retry ngoài transaction có thể tạo transaction mới mỗi attempt; retry trong transaction có thể tiếp tục trên rollback-only state. Test call chain và side effects thay vì chỉ kiểm số lần gọi.