Spring MVC異步處理架構實戰:線程池+消息隊列+事件驅動+反應式高并發性能優化
在高并發的分布式系統中,異步處理已成為提升性能、保障穩定性的核心技術手段。本文通過 + 15個真實代碼案例,帶你徹底掌握:
- 異步 vs 同步的核心抉擇
- 何時該用異步?(日志記錄、消息推送)
- 何時必須同步?(支付交易、庫存扣減)
- 從 電商訂單 到 物聯網指令 的六大場景深度對比
- 四大異步方案實戰
- 線程池優化:Spring
@Async
配置陷阱與性能調優 - 消息隊列:RabbitMQ 如何實現可靠異步通信(含死信隊列設計)
- 事件驅動:Spring Events 解耦業務模塊的最佳實踐
- 反應式編程WebFlux 在IO密集型場景的碾壓式優勢
- 血的教訓:
- 異步處理支付導致 資金損失 的案例
- 庫存扣減異步化引發 超賣事故 的復盤
- 從CAP理論看異步與一致性的 終極權衡
異步處理原則
一、異步處理方式全景圖
1.1 異步方式選擇
圖片
1.2 異步決策樹
圖片
二、架構設計圖
圖片
三、實現說明
原則核心:將耗時操作異步化,快速釋放請求線程
未實現前代碼:
@PostMapping("/order")
publicResultcreateOrder(@RequestBodyOrderDTO dto){
// 同步處理所有邏輯
orderService.validate(dto);// 校驗
orderService.lockStock(dto);// 鎖庫存
orderService.create(dto);// 創建訂單(數據庫IO)
orderService.sendSms(dto);// 發短信(網絡IO)
returnResult.success();
}
問題:線程被長時間占用,并發能力低
實現后代碼:
// 配置線程池
@Configuration
publicclassAsyncConfigimplementsAsyncConfigurer{
@Override
publicExecutorgetAsyncExecutor(){
ThreadPoolTaskExecutor executor =newThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(100);
executor.setQueueCapacity(1000);
executor.setThreadNamePrefix("Async-Executor-");
executor.initialize();
return executor;
}
}
@Service
publicclassAsyncOrderService{
@Async// 異步方法
publicvoidasyncCreateOrder(OrderDTO dto){
orderService.validate(dto);
orderService.lockStock(dto);
orderService.create(dto);
}
@Async
publicvoidasyncSendSms(OrderDTO dto){
orderService.sendSms(dto);
}
}
@RestController
publicclassOrderController{
@Autowired
privateAsyncOrderService asyncOrderService;
@PostMapping("/order")
publicResultcreateOrder(@RequestBodyOrderDTO dto){
// 主流程同步處理
orderService.validate(dto);
// 異步處理耗時操作
asyncOrderService.asyncCreateOrder(dto);
asyncOrderService.asyncSendSms(dto);
returnResult.success("訂單處理中");
}
}
優勢:
- 請求響應時間從2s降低到200ms
- Tomcat線程池利用率從90%降到30%
- 系統吞吐量提升5倍
四、各種異步處理實現方式詳解
4.1. 線程池方式(@Async)
適用場景:短耗時任務(<1秒),如日志記錄、通知發送
@Configuration
@EnableAsync
publicclassAsyncConfigimplementsAsyncConfigurer{
@Override
publicExecutorgetAsyncExecutor(){
ThreadPoolTaskExecutor executor =newThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(50);
executor.setQueueCapacity(1000);
executor.setThreadNamePrefix("Async-Executor-");
executor.setRejectedExecutionHandler(newThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
@Service
publicclassNotificationService{
@Async// 使用默認線程池
publicvoidsendSms(String phone,String content){
// 模擬耗時操作
Thread.sleep(300);
smsClient.send(phone, content);
}
@Async("emailExecutor")// 指定特定線程池
publicvoidsendEmail(Email email){
emailSender.send(email);
}
}
參數調優建議:
corePoolSize
:CPU密集型建議N+1,IO密集型建議2N(N=CPU核心數)queueCapacity
:根據任務平均處理時間和可接受延遲設置
4.2. 消息隊列方式(RabbitMQ)
適用場景:跨服務異步、削峰填谷、保證最終一致性
@Configuration
publicclassRabbitConfig{
@Bean
publicQueueorderQueue(){
returnnewQueue("order.queue",true);// 持久化隊列
}
}
@Component
publicclassOrderMessageSender{
@Autowired
privateRabbitTemplate rabbitTemplate;
publicvoidsendCreateOrder(Order order){
rabbitTemplate.convertAndSend(
"order.exchange",
"order.create",
order,
message ->{
message.getMessageProperties().setPriority(5);// 設置優先級
return message;
});
}
}
@Component
@RabbitListener(queues ="order.queue")
publicclassOrderMessageHandler{
publicvoidhandleCreateOrder(Order order){
orderService.processOrderCreation(order);
}
}
消息可靠性保障:
- 生產者確認模式(publisher confirms)
- 消費者手動ACK
- 死信隊列處理失敗消息
4.3. 事件驅動方式(Spring Events)
適用場景:應用內部模塊解耦
// 定義領域事件
publicclassOrderCreatedEventextendsApplicationEvent{
privateOrder order;
publicOrderCreatedEvent(Object source,Order order){
super(source);
this.order = order;
}
// getter...
}
@Service
publicclassOrderService{
@Autowired
privateApplicationEventPublisher eventPublisher;
@Transactional
publicOrdercreateOrder(OrderDTO dto){
Order order =convertToOrder(dto);
orderRepository.save(order);
// 發布領域事件
eventPublisher.publishEvent(newOrderCreatedEvent(this, order));
return order;
}
}
@Component
publicclassOrderEventHandler{
@EventListener
@Async
publicvoidhandleOrderCreated(OrderCreatedEvent event){
// 發送通知
notificationService.sendOrderCreated(event.getOrder());
// 更新統計數據
statsService.updateOrderStats(event.getOrder());
}
}
4.4. 反應式編程(WebFlux)
適用場景:高并發IO密集型服務
@RestController
@RequestMapping("/products")
publicclassProductController{
@GetMapping("/{id}")
publicMono<Product>getProduct(@PathVariableString id){
return productReactiveRepository.findById(id)
.timeout(Duration.ofMillis(500))
.onErrorResume(e ->Mono.just(getFallbackProduct()));
}
@PostMapping
publicMono<Void>createProduct(@RequestBodyMono<Product> product){
return product
.flatMap(p -> productReactiveRepository.save(p))
.then();
}
}
五、不適合異步處理的業務場景
圖片
5.1 核心業務(O)
不能異步的原因:
- 關鍵路徑依賴:核心業務是用戶操作的主流程,異步化會導致流程斷裂
- 用戶體驗破壞:用戶需要立即知曉操作結果(如支付成功/失敗)
- 故障難以恢復:失敗后補償邏輯復雜,可能造成業務損失
典型反例:
// 同步處理支付(必須立即返回結果)
@PostMapping("/payment")
publicPaymentResultprocessPayment(@RequestBodyPaymentRequest request){
// 同步執行所有核心步驟
validationService.validate(request);
balanceService.debit(request.getAccount(), request.getAmount());
paymentRecordService.create(request);
returnPaymentResult.success();// 必須同步返回
}
5.2 強一致性要求(P)
不能異步的原因:
- 數據實時可見:后續操作依賴最新狀態(如庫存扣減)
- 避免臟讀風險:異步可能導致其他線程讀到中間狀態
- 事務完整性:跨服務調用需要同步事務協調
典型反例:
@Transactional
publicvoidplaceOrder(Order order){
// 必須同步保證庫存和訂單的強一致
inventoryService.lockStock(order.getItems());// 同步調用
orderRepository.save(order);
// 非核心操作可以異步
asyncService.logOrderActivity(order);
}
5.3 需要即時反饋(Q)
不能異步的原因:
- 用戶交互需求:前端需要立即展示結果(如表單提交)
- 避免輪詢復雜度:減少客戶端狀態輪詢邏輯
- 操作連續性:下一步操作依賴當前結果(如兩步驗證)
典型反例:
// 用戶登錄必須同步返回token
@PostMapping("/login")
publicAuthResultlogin(@RequestBodyLoginRequest request){
User user = authService.authenticate(request);// 同步驗證
String token = tokenService.generate(user);
returnnewAuthResult(token);// 立即返回
}
5.4 事務邊界內操作(R)
不能異步的原因:
- 事務原子性:異步操作無法加入數據庫事務
- 臟數據風險:主事務回滾時異步操作已執行
- 執行順序問題:異步可能導致后續操作先于前置完成
典型反例:
@Transactional
publicvoidupdateProfile(User user){
// 同步執行(必須在事務內)
userDao.update(user);
permissionService.refresh(user.getId());// 同步調用
// 異步操作會導致事務問題:
// asyncService.logUserUpdate(user); ?
}
解決方案:
@Transactional
publicvoidupdateProfile(User user){
userDao.update(user);
permissionService.refresh(user.getId());
// 事務提交后再異步處理
TransactionSynchronizationManager.registerSynchronization(
newTransactionSynchronization(){
@Override
publicvoidafterCommit(){
asyncService.logUserUpdate(user);
}
}
);
}
5.5 簡單查詢(S)
不能異步的原因:
- 性能反模式:異步開銷可能超過查詢本身
- 代碼復雜度:Future/Callback增加理解成本
- 資源浪費:線程切換消耗高于直接查詢
性能對比:
查詢類型 | 同步耗時 | 異步耗時(含線程切換) |
主鍵查詢(1ms) | 1ms | 10ms+ |
簡單JOIN(5ms) | 5ms | 15ms+ |
正確實踐:
// 直接同步查詢
@GetMapping("/users/{id}")
publicUsergetUser(@PathVariableString id){
return userDao.findById(id);// 簡單查詢無需異步
}
5.6 總結:不能異步的核心本質
場景 | 核心矛盾 | 技術限制 | 業務風險 |
核心業務 | 流程連續性與異步斷點 | 無法保證操作原子性 | 業務流程中斷 |
強一致性 | 數據新鮮度與延遲不可調和 | CAP理論約束 | 數據不一致 |
即時反饋 | 用戶交互的實時性要求 | 前端狀態管理復雜度 | 用戶體驗差 |
事務邊界內 | 事務ACID與異步不可控的矛盾 | 分布式事務實現復雜度 | 數據污染 |
簡單查詢 | 性能收益與異步開銷的負向博弈 | 線程上下文切換成本 | 系統吞吐量下降 |
通過理解這些底層限制,可以更準確地判斷何時應該避免異步化設計。同步與異步的選擇本質上是一致性、可用性和性能之間的權衡(CAP三角的具象化表現)。
5.7. 典型不適用場景示例
5.7.1 支付處理
錯誤異步實現:
@PostMapping("/pay")
publicResultpay(@RequestBodyPaymentRequest request){
// 錯誤:異步處理支付核心邏輯
paymentService.asyncProcessPayment(request);
returnResult.success("處理中");
}
問題分析:
- 無法即時返回支付結果
- 難以處理支付失敗情況
- 客戶端需要復雜輪詢機制
正確同步實現:
@PostMapping("/pay")
@Transactional
publicResultpay(@RequestBodyPaymentRequest request){
// 同步處理支付
PaymentResult result = paymentService.process(request);
// 同步記錄交易
transactionService.record(result);
returnResult.success(result);
}
5.7.2 庫存扣減
錯誤異步實現:
publicvoidplaceOrder(Order order){
// 錯誤:異步扣減庫存
inventoryService.asyncReduceStock(order.getItems());
// 可能造成超賣
orderDao.save(order);
}
正確實現:
@Transactional
publicvoidplaceOrder(Order order){
// 先同步扣減庫存
inventoryService.reduceStock(order.getItems());
// 再創建訂單
orderDao.save(order);
// 其他非關鍵操作異步化
eventPublisher.publishEvent(newOrderCreatedEvent(order));
}
六、適合異步處理的業務場景
圖片
6.1 非核心路徑業務
為什么能異步:
- 不影響主流程:這些業務不是用戶操作的關鍵路徑,即使延遲或失敗也不會直接影響主要功能
- 故障隔離:異步執行可以將非核心業務的故障與核心流程隔離
- 資源分配優先級:系統資源可以優先保障核心業務
典型場景:
- 用戶行為日志記錄
- 操作審計跟蹤
- 數據分析收集
實現示例:
// 同步方式(不推薦)
@PostMapping("/order")
publicOrdercreateOrder(OrderDTO dto){
Order order = orderService.create(dto);// 核心業務
logService.recordOperationLog("create_order", dto);// 非核心日志
return order;
}
// 異步優化
@PostMapping("/order")
publicOrdercreateOrder(OrderDTO dto){
Order order = orderService.create(dto);// 同步處理核心
// 異步處理非核心日志
CompletableFuture.runAsync(()->{
logService.recordOperationLog("create_order", dto);
}, asyncExecutor);
return order;
}
6.2 允許延遲的業務
為什么能異步:
- 時間容忍度高:業務本身對處理時效要求不高(秒級甚至分鐘級延遲可接受)
- 批量處理機會:可以積累一定量后批量處理,提高效率
- 最終一致性:不需要實時強一致,只要最終數據正確即可
典型場景:
- 報表生成
- 數據統計分析
- 推薦系統更新
實現示例:
// 用戶行為分析處理
@EventListener
@Async
publicvoidhandleUserBehaviorEvent(UserBehaviorEvent event){
// 延遲5分鐘處理,積累更多數據
TimeUnit.MINUTES.sleep(5);
// 批量處理期間收集的所有事件
List<UserBehaviorEvent> events = eventBuffer.getEvents(event.getUserId());
analysisService.processUserBehavior(events);
}
6.3 無需即時反饋的業務
為什么能異步:
- 客戶端無等待需求:用戶不需要立即知道處理結果
- 后臺靜默處理:結果可以通過其他渠道通知(如郵件、站內信)
- 降低交互復雜度:避免前端長時間等待響應
典型場景:
- 大文件導出
- 系統消息推送
- 后臺數據處理任務
實現示例:
@PostMapping("/export")
publicResponseEntity<String>exportLargeData(@RequestBodyExportRequest request){
// 立即返回任務ID
String taskId =generateTaskId();
// 異步執行導出
exportService.asyncExport(taskId, request);
returnResponseEntity.accepted()
.header("Location","/tasks/"+taskId)
.body("{"taskId":""+taskId+""}");
}
// 客戶端可以通過taskId輪詢狀態
@GetMapping("/tasks/{taskId}")
publicTaskStatusgetTaskStatus(@PathVariableString taskId){
return taskService.getStatus(taskId);
}
6.4 資源密集型業務
為什么能異步:
- 避免資源爭用:將CPU/IO密集型操作與主線程隔離
- 彈性擴展:可以通過專用線程池或工作節點處理
- 防止主流程阻塞:長時間運行的任務不會拖慢核心響應
典型場景:
- 圖像/視頻處理
- 復雜計算任務
- 大數據處理
實現示例:
// 圖片縮略圖生成
@PostMapping("/upload")
publicStringuploadImage(@RequestParamMultipartFile file){
String imageId = storageService.store(file);
// 同步返回ID后異步處理縮略圖
imageProcessingExecutor.submit(()->{
Thumbnailator.createThumbnail(
storageService.getPath(imageId),
storageService.getThumbnailPath(imageId),
200,200
);
});
return imageId;
}
6.5 最終一致的業務
為什么能異步:
- 降低分布式事務復雜度:避免同步的分布式事務
- 提高可用性:部分服務不可用時仍可繼續處理
- 通過重試保證最終成功:失敗操作可以自動重試
典型場景:
- 跨服務數據同步
- 支付后的積分發放
- 訂單完成后的庫存結算
實現示例:
// 訂單支付后的積分處理
@TransactionalEventListener(phase =AFTER_COMMIT)
publicvoidhandleOrderPaidEvent(OrderPaidEvent event){
try{
// 異步增加用戶積分(可能失敗)
pointService.addPoints(
event.getUserId(),
event.getAmount()/100,
"訂單獎勵");
}catch(Exception e){
// 失敗后進入重試隊列
retryQueue.push(newRetryTask(
()-> pointService.addPoints(...),
3// 最大重試次數
));
}
}
6.6. 典型適用場景示例
6.6.1 用戶行為日志記錄
同步實現問題:
@PostMapping("/login")
publicResultlogin(@RequestBodyLoginDTO dto){
// 核心登錄邏輯
User user = authService.authenticate(dto);
// 同步記錄日志(阻塞主流程)
logService.saveLoginLog(user.getId());
returnResult.success(user);
}
異步優化方案:
@PostMapping("/login")
publicResultlogin(@RequestBodyLoginDTO dto){
User user = authService.authenticate(dto);
// 異步記錄日志
eventPublisher.publishEvent(newUserLoginEvent(user.getId()));
returnResult.success(user);
}
@Async
@EventListener
publicvoidhandleLoginEvent(UserLoginEvent event){
logService.saveLoginLog(event.getUserId());
}
6.6.2 訂單狀態流轉
同步實現問題:
@Transactional
publicvoidcancelOrder(String orderId){
// 1. 更新訂單狀態
orderDao.updateStatus(orderId,OrderStatus.CANCELLED);
// 2. 釋放庫存(同步調用)
inventoryService.unlockStock(orderId);
// 3. 退款處理(同步調用)
paymentService.refund(orderId);
// 4. 通知用戶
notificationService.sendCancelNotice(orderId);
}
異步優化方案:
@Transactional
publicvoidcancelOrder(String orderId){
// 1. 只處理核心狀態變更
orderDao.updateStatus(orderId,OrderStatus.CANCELLED);
// 2. 發送領域事件
eventPublisher.publishEvent(newOrderCancelledEvent(orderId));
}
// 各處理步驟異步化
@TransactionalEventListener(phase =AFTER_COMMIT)
publicvoidhandleOrderCancelled(OrderCancelledEvent event){
// 異步釋放庫存
inventoryService.asyncUnlockStock(event.getOrderId());
// 異步退款
paymentService.asyncRefund(event.getOrderId());
// 異步通知
notificationService.asyncSendCancelNotice(event.getOrderId());
}
6.7 異步處理的優勢矩陣
業務特征 | 異步優勢 | 技術實現方案 |
非核心路徑 | 保障核心業務穩定性 | 線程池隔離(@Async) |
允許延遲 | 提高系統吞吐量 | 延遲隊列(RabbitMQ TTL+DLX) |
無需即時反饋 | 改善用戶體驗 | 輪詢機制+任務隊列 |
資源密集型 | 避免主流程阻塞 | 專用線程池/工作節點 |
最終一致 | 簡化分布式系統架構 | 事件溯源(Event Sourcing)+重試機制 |
通過理解這些底層原因,開發者可以更準確地判斷何時應該采用異步處理,以及選擇最適合的異步實現方式。異步處理本質上是通過空間換時間(更多線程/節點)和時間換可靠性(重試/持久化)來提升系統整體效能的設計哲學。
七、異步處理決策矩陣
業務特征 | 推薦處理方式 | 技術方案 | 注意事項 |
高頻低耗時 | 線程池異步 | @Async + ThreadPoolTaskExecutor | 注意線程池配置 |
跨服務解耦 | 消息隊列 | RabbitMQ/Kafka | 保證消息可靠性 |
應用內模塊解耦 | 事件驅動 | Spring Events | 注意事件監聽順序 |
高并發IO密集型 | 反應式編程 | WebFlux/RxJava | 學習曲線較陡 |
長耗時任務 | 任務隊列 | Redis Queue + Worker | 實現進度跟蹤 |
實時性要求高 | 同步處理 | 傳統Servlet模型 | 優化數據庫訪問 |
八、異步處理的底層原理
- 線程/協程切換:將任務交給其他執行單元,釋放主線程
// Java線程池任務提交
executor.submit(()->{
// 在另一個線程執行
});
- 事件循環機制:非阻塞IO處理(如Netty)
channel.eventLoop().execute(()->{
// 在IO線程執行
});
- 消息持久化:通過消息隊列保證任務不丟失
// RabbitMQ消息發送
rabbitTemplate.convertAndSend(
"exchange",
"routingKey",
message);
- 回調機制:任務完成后通知
CompletableFuture.supplyAsync(()->{
returnlongTimeOperation();
}).thenAccept(result ->{
// 完成后處理
});
九、異步處理落地經驗
- 明確邊界:
- 核心業務流程保持同步
- 周邊服務異步化
- 異常處理:
@Async
publicvoidasyncTask(){
try{
// 業務邏輯
}catch(Exception e){
// 1. 記錄詳細日志
log.error("Async task failed", e);
// 2. 重試機制
retryTemplate.execute(ctx ->{
returndoBusiness();
});
// 3. 死信隊列處理
deadLetterQueue.send(failedMessage);
}
}
- 監控指標:
@Bean
publicMeterRegistryCustomizer<MeterRegistry>asyncMetrics(){
return registry ->{
newThreadPoolMetrics(
asyncExecutor,
"app.async.pool",
Tags.empty()
).bindTo(registry);
};
}
- 上下文傳遞:
@Configuration
publicclassAsyncConfigimplementsAsyncConfigurer{
@Override
publicExecutorgetAsyncExecutor(){
// 支持MDC上下文傳遞
returnnewMdcThreadPoolTaskExecutor();
}
}
通過合理運用異步處理技術,可以使系統獲得:
- 吞吐量提升5-10倍
- 響應時間降低60%以上
- 資源利用率提高3倍
- 更好的故障隔離能力
十、其他適合異步處理的場景
10.1 系統維護類任務
10.1.1 數據備份與歸檔
適合原因:
- 通常在后半夜執行,不影響白天業務
- 數據量大,耗時長
- 不需要即時結果反饋
@Scheduled(cron ="0 0 2 * * ?")// 每天凌晨2點
@Async
publicvoidasyncDatabaseBackup(){
backupService.performIncrementalBackup();
auditService.logBackupOperation();
cleanupService.removeOldBackups();
}
10.1.2 緩存預熱
適合原因:
- 可以在系統低峰期預先執行
- 避免首次請求的延遲
- 失敗不影響核心功能
@PostConstruct
@Async
publicvoidwarmUpCaches(){
hotProductService.preloadTop100Products();
categoryTreeCache.rebuild();
recommendationModel.refresh();
}
10.2用戶體驗優化類
10.2.1 預加載與預計算
適合原因:
- 預測用戶可能需要的資源提前加載
- 計算過程對用戶透明
- 即使失敗也不影響當前操作
@GetMapping("/product/{id}")
publicProductgetProduct(@PathVariableString id){
Product product = productService.getById(id);
// 異步預加載關聯商品
CompletableFuture.runAsync(()->{
relatedProductService.preloadFor(product);
}, ioExecutor);
return product;
}
10.2.2 漸進式頁面渲染
適合原因:
- 優先返回核心內容
- 次要內容后續異步加載
- 提升用戶感知速度
@GetMapping("/dashboard")
publicCompletableFuture<Dashboard>getDashboard(){
CompletableFuture<UserProfile> profileFuture = userService.getProfileAsync();
CompletableFuture<List<Notification>> noticesFuture = noticeService.getLatestAsync();
returnCompletableFuture.allOf(profileFuture, noticesFuture)
.thenApply(ignored ->{
Dashboard dashboard =newDashboard();
dashboard.setProfile(profileFuture.join());
dashboard.setNotices(noticesFuture.join());
return dashboard;
});
}
10.3 基礎設施類操作
10.3.1 服務健康檢查
適合原因:
- 定期后臺執行
- 失敗只需記錄告警
- 不需要阻塞主流程
@Scheduled(fixedRate =300_000)
@Async("healthCheckExecutor")
publicvoidperformHealthChecks(){
serviceRegistry.listAllServices()
.parallelStream()
.forEach(service ->{
HealthStatus status = healthChecker.check(service);
healthDashboard.update(status);
});
}
10.3.2 配置動態刷新
適合原因:
- 可以分批逐步更新
- 允許重試機制
- 新舊配置可短暫共存
@EventListener(ConfigUpdateEvent.class)
@Async
publicvoidhandleConfigUpdate(ConfigUpdateEvent event){
configManager.reload(event.getKeys())
.retryWhen(Retry.backoff(3,Duration.ofSeconds(1)))
.subscribe();
}
10.4 數據處理類任務
10.4.1 數據ETL(抽取-轉換-加載)
適合原因:
- 處理流程可分階段異步執行
- 單個步驟失敗可重試
- 最終結果一致即可
publicvoidstartEtlJob(JobConfig config){
extractData(config)
.thenApplyAsync(this::transformData, transformPool)
.thenAcceptAsync(this::loadData, loadPool)
.exceptionally(e ->{
jobMonitor.recordFailure(e);
returnnull;
});
}
10.4.2 機器學習模型訓練
適合原因:
- 訓練過程耗時極長
- 可以容忍訓練延遲
- 支持訓練中途停止/繼續
@PostMapping("/models")
publicResponseEntity<String>trainModel(@RequestBodyTrainingSpec spec){
String jobId = modelService.submitTrainingJob(spec);
returnResponseEntity.accepted()
.header("Location","/jobs/"+jobId)
.body(jobId);
}
10.5 網絡通信類
10.5.1 第三方API調用
適合原因:
- 網絡延遲不可控
- 第三方服務可能不穩定
- 通常不需要即時響應
@Async
publicCompletableFuture<ThirdPartyResponse>callExternalApi(ApiRequest request){
return restTemplate.exchangeAsync(request.toUri(),
request.getMethod(),
request.getEntity(),
request.getResponseType());
}
10.5.2 WebSocket消息廣播
適合原因:
- 客戶端接收能力不同
- 允許消息延遲
- 支持消息重傳
@Async
publicvoidbroadcastChatMessage(ChatMessage message){
Set<WebSocketSession> sessions = chatRoom.getSessions(message.getRoomId());
sessions.forEach(session ->{
if(session.isOpen()){
session.sendAsync(message.toText());
}
});
}
10.6 特殊業務場景
10.6.1 預約排隊系統
適合原因:
- 排隊過程可以后臺處理
- 結果可以通過推送通知
- 支持排隊狀態查詢
@PostMapping("/reservations")
publicStringcreateReservation(@RequestBodyReservationRequest request){
String queueId = queueService.enqueue(request);
reservationProcessor.processAsync(queueId)
.thenAccept(result ->{
notificationService.sendReservationResult(
request.getUserId(),
result);
});
return queueId;
}
10.6.2 物聯網設備指令
適合原因:
- 設備響應時間不確定
- 支持指令重試
- 結果可以異步回調
publicvoidsendDeviceCommand(DeviceCommand command){
commandQueue.publish(command);
// 異步等待響應
deviceResponseSubscriber.waitForResponse(command.getId())
.orTimeout(30,TimeUnit.SECONDS)
.thenAccept(this::handleResponse);
}