Why Javaer should try Kotlin ?

Jian-Min Huang
4 min readMay 22, 2021

承自上篇的拖稿,我來講為什麼我認為 Coroutine 是 Spring Backend Side 下一個世代的主流。其實併發請求在前端已經是十分常見的撰寫方式,但過去後端在這方面一直不是十分普及。

原因有幾個,一者 Blocking 寫法相對簡單,專案的流量量級如果不大,直接垂直擴展升規格輾過去是常見而有效的解法。第二是併發式的寫法相對複雜,提高不少門檻。最後當然這跟整個生態系對於 Non-Blocking 的支援也有一點關係。

Talk is cheap. Show me the code.

這邊讓我們先來看一段很一般的 Spring MVC Sequential Blocking Call

這雖然是我特別設計的案例,不過希望你可以明白前兩個 Action 是獨立的而可以併發,併發相對就能降低 cost 從 100 + 200 -> 200。

第三個 Action 要相依前兩個 Action 的結果。

最後兩個 Action 相依第三個 Action 的結果,也設計成可以併發,併發相對就能降低 cost 從 400 + 500 -> 500。

所以如果本來依序 Blocking Call 的話,固定的時間成本就是 100 + 200 + 300 + 400 + 500 = 1500,但是如果你適當地用併發,理論上應該可以降低成 200 + 300 + 500 = 1000。一來一往相差 500ms,這差距應該不用我多說。

那接下來進入我們的正題,Coroutine。其實無論是 自己控制Thread Pool、CompletableFuture、Reactive、Coroutine 等等。要完成非同步的併發終歸是要靠背景的 Thread 完成,在這邊我其實不會把重點放在講解 Coroutine 的原理,其實他也不是什麼黑魔法,就是 CPS Style 的 Callback 大法。在這邊我是想展示所謂用 Blocking Style 寫出 Non-Blocking Code 是怎麼回事。

排版是有故意對齊一下,但寫起來的風格是真的很像,真的很推薦試看看!雖然我們可能會被 JavaScript Coder 笑,不過就是個 Await 這麼驚訝!不過這對後端真的是很大的一步,尤其是如果你被 CompletableFuture 或是 RX 系列的凌虐過 XDD。下面我也附上 CompletableFuture 和 Reactor 的範例程式碼,如果你有更好更美的寫法歡迎留言給我知道喔。

umm,應該不會有人跟我說下面這兩種比較好寫吧,你484被虐得不輕 XDD。其實 Servlet 3 開始就支援回傳 CompletableFuture,而 Mono 或是 Flux 則是 Spring WebFlux 的範疇。那麼寫法這麼多,也許有人會問誰比較快?

關於這個我們以後會專門做一期為大家講解的 (老高梗

認真來說,快這個字太模糊了,畢竟不知道你是指生產力高還是指效能好。但可以確認的是,生產力的變因其實很多,只討論這個意思不大。不過效能我倒是可以告訴你,在正確的狀況下使用,差距很小,而且 JVM 通常也沒在跟人家拼絕對速度,看看旁邊竊笑的 Go 和 Rust 同學好嗎?

不過公開演講的部分應該會在今年 COSCUP JVM 議程軌會第一次亮相,會比較一些 Java Backend Server Model 跟情境,再提供詳細的實驗數據和心得給大家 (結果還是老高嘛😂

好啦,Repo在這邊,陸續補上囉。https://github.com/b2etw/reactive-coroutine-performance-test

最後的結論部分就讓我來講點古,以過去 Java Spring Backend 的背景來說,Non-Blocking 沒有那麼流行也是有道理的。自從 Spring 進入 5 開始大力擁抱 Reactive 之後,整合周邊的 API 也才大幅流行起來。

Network IO 部分,最常用的 RestTemplate 目前已經是 Deprecated,之後會改成 WebClient。而各家資料庫的 Reactive 驅動也還在陸續到位,這部分 NoSQL 進展比較快,RDB 用的 R2DBC 雖然也已經正式 Release 但採用度還要觀望一下。

再來就是無論是 low level 或是 high level 的併發編寫技巧其實門檻都蠻高的,現實的是某些團隊可能連 Blocking 都不一定寫得好,更別說你要弄成併發版本的,當然這跟系統一開始的架構設計也有關係就是。

最後就是流量議題,畢竟錢包的重量決定伺服器的能量。流量不大的話,垂直擴展加機器的確是常見而有效的做法。不過程式的 Bottleneck 是無法用物理的方法解決的唷,而其實就算你的機器撐得住你也應該思考要怎麼更省錢。

期待能看到使用 Spring Framework with Kotlin 的團隊越來越多,也希望有機會能跟大家多多交流,歡迎在下面給我 Feedback 👀

--

--