Spring WebFlux效能真的超過Spring Servlet ? - Gavin

banq發表於2021-09-05

如何構建高效能系統一直是開發人員感興趣的話題。很多業內人士提倡非阻塞程式設計的正規化,表示基於非阻塞程式設計的應用相比傳統的阻塞技術指令式程式設計,可以更高效地利用資源,實現更高的效能。
許多文章解釋了非阻塞程式設計的好處,它似乎是一種優越且面向未來的解決方案。但是,如果沒有第一手經驗來證明,我不相信。為了找出真相,我使用 2 個不同的框架構建了同一個 Java 應用程式——Spring WebFlux(非阻塞)和 Spring Servlet(阻塞),然後進行了一系列實驗,以比較兩種實現之間的系統效能。令人驚訝的是,研究結果表明,在某些環境設定中,非阻塞程式設計並不總是比阻塞程式設計更好。
在本文中,您將瞭解有關 Spring WebFlux 的真相。我將與您分享我的實驗細節和效能測試結果的分析。
 

什麼是阻塞和非阻塞?
回到基礎。什麼是阻塞?在傳統的計算機程式設計中,每一行程式程式碼都是一條同步指令執行。換句話說,機器一個接一個地執行程式邏輯,直到當前指令完全執行後才會執行下一行程式碼。
使用阻塞程式設計實現的此類系統通常效能非常好。但是,如果任何程式的執行需要時間才能完成,系統執行緒就會卡住,如果情況惡化,將導致系統崩潰。
相反,非阻塞程式設計以釋出-訂閱模式實現程式邏輯。主程式流執行程式並訂閱結果。主程式不會被當前流程執行“阻塞”,而是繼續流程並立即執行下一個流程。流程執行完成後,透過回撥通知主程式,以繼續執行程式邏輯。
理論上,非阻塞程式設計實現了並行性。更重要的是,它不會阻塞任何不專用於任何請求的系統執行緒,並且執行緒池處理任何已釋出的回撥。
 
 

Java Spring 如何支援這兩種正規化?
Java Spring 在 2 個獨立的技術棧中支援阻塞和非阻塞程式設計——Spring Servlet(阻塞)和 Spring WebFlux(非阻塞)。由於系統執行緒模型的機制不同,兩種實現的底層技術有很大的不同。
 

效能測試實現
示例應用程式是一個 Spring Boot API,它提供了外匯匯率查詢和外幣交易功能。該系統依靠外部 API 獲取最新匯率並提供貨幣對的買入和賣出價格。
現在,讓我們看看效能測試設計。負載測試是使用強大的工具 Gatling 構建的。在 30 秒內將使用者每秒的負載注入量從 10 個增加到 40 個,然後在 30 秒內保持每秒 40 個使用者的恆定注射量。
為了模擬現實生活中的情況,每個使用者都被分配了一個使用者旅程來提交用於匯率查詢、匯率預訂和交易提交的 API 請求。
有關測試場景設計以及如何使用 Gatling 構建負載測試的詳細資訊,請參閱本文
..更多點選標題
  

假設有一個非常慢的外部 API,在更重的工作負載下有什麼區別?
預計當工作量增加一倍而外部 API 仍然很慢時,情況會更糟。哪種實施可以在艱難的情況下倖存下來?
要使工作負載加倍,請執行此命令列以使用引數來觸發 Gatling 負載測試,以指定每秒初始使用者數和每秒目標使用者數。
結果表明,Spring Servlet 無法處理大部分請求,失敗率高達 89%。相反,Spring WebFlux 仍然可以在惡劣的條件下生存,儘管失敗率增加了 17%,響應時間在 30 秒左右。
 

結論
測試證明,基於非阻塞技術的應用總體上優於傳統的阻塞技術。儘管在 I/O 程式訪問外部API很快的理想環境中,非阻塞技術的威力是看不出來的,但這種技術是有優勢的,在現實生活中肯定會實現更快的響應時間和更低的故障率,因為外部 API 和持久儲存可能由於各種原因,並不總是達到預期的服務水平,尤其是服務因大量傳入流量而不堪重負。
因此,在使用 Java 進行 API 開發時,Spring WebFlux 是優於 Spring Servlet 的推薦框架。在您的新 API 開發中採用此框架是值得投入時間和資源的。

 

相關文章