Java 微服務框架新選擇:Spring 5
在這篇文章中,我們將討論即將發布的第五代 Spring 框架中的新概念—— 「Functional Web Framework」,來看看它如何幫助我們構建輕量級的微服務。
你可能會對標題中出現的 「Spring」 和 「微服務框架」感到驚訝。但是確實如此,Spring 5非常適合成為你 Java Web 微服務框架的新選擇。首先,為了避免混淆讓我們來對「微服務」中的「微」達成共識:
簡潔 - 無需樣板工程,無需額外設置
簡單 - 沒有任何「魔法」
易於部署 - 產生單一的可部署工件
容易運行 - 沒有額外的依賴
輕量級 - 最小內存佔用/CPU 使用
非阻塞 - 更好的並發性
雖然 Spring Boot 已經能做到上述的一些點,但 Spring MVC 本身依然引入了很多魔法。比如 @Controller
這個廣泛使用的註解就有點含糊不清,更不用說 Spring 的自動配置和組件掃描等特性了。通常來說,這是開發一個大規模應用時可以承受的煩惱,畢竟 Spring 幫我們搞定了依賴注入、請求路由、各類複雜的配置等。然而,在微服務的世界中,應用程序只是類似一個大機器中運行的小齒輪,Spring Boot 就顯得有些「殺雞用牛刀」了。
為了解決這些問題,Spring 團隊引出了一個名為「Functional Web Framework」的新概念,它是 Spring WebFlux(以前稱為 Spring Reactive Web)這個大項目的一部分。同時也是我們現在要討論的。
首先,讓我們回顧一下基礎知識,看看一個 Web 應用程序到底是什麼樣的,以及由什麼組件構成。很顯然,最基本的部分就是網路伺服器(Web server)本身,為了避免手工解析 HTTP 請求,然後委派給應用程序的某個方法,我們需要一個請求路由器(router),同時我們也需要一個請求處理器或處理程序(handler),其實就是一段代碼,它可以接受請求,做實際的邏輯處理,並最終返回一個響應。所有這些也正是 Spring Functional Web 所做的,它剝離了所有的抽象層(beans 和 contexts)。注意,這並不意味著它脫離並放棄了成熟的 Spring MVC 模型,而是提供了使用 Spring 來構建 Web 應用程序的另一種選擇。
請求處理器
我們來看一下這個例子。 開始前請訪問 http://start.spring.io使用項目創建器創建一個新的空白工程,使用 Spring Boot 2.0 和 Reactive Web 作為唯一的依賴。 接著我們就可以定義第一個請求處理器或處理方法(handler)了,很簡單,它接受請求並返迴響應。
從上述代碼可以看出來,它是 HandlerFunction
介面的一個實現,定義了一個方法來獲取一個請求(類型為ServerRequest
),並返回具有"Hello"
字元串的ServerResponse
對象。 Spring 還提供了方便的構建器(builder)來構造響應。在我們的例子中,我們使用ok
自動將返回碼設置為HTTP 200 。
為了構造響應體,我們使用另一個叫Mono的概念,它代表single reactive value,但我們這裡先不管它,只要明白Mono.just(...) 是
一種通過返回Publisher 類型對象(其實是類似 Promise)
來實現非阻塞編程範式的方式。Reactive Web 是Spring 5 的一部分,它是通過 Java 9 的Reactive Stream來實現的。你可以參考 Dave Syer 的這篇文章。
我們還可以使用 Java 8 的 lambdas 表達式使代碼更簡潔,如下:
請求路由器上面我們已經有一個 handler 了,現在我們可以定義一個請求路由器了。 假設我們要使用 GET
方法請求"/"
時調用我們的 handler。 為此,我們可以使用RouterFunction
。
route
和GET
都是RequestPredicates
和RouterFunctions
的靜態方法,它們可以用來構建RouterFunction
。它接受一個請求,檢查它是否能匹配現有handler(比如請求路徑(path)、請求方法(method)或者是內容類型(content type)等)。如果匹配則調用 handler。 在我們的例子中,HTTP 方法是 GET,請求路徑是"/"
, handler 函數是上面定義的hello
。
現在我們可以把他們組裝在一起來完成整個應用程序。我們將使用非常輕量、簡單的 Reactive Netty 作為 Web 伺服器。要將我們的請求路由器集成到 Web 伺服器中,我們需要將其轉換為 HttpHandler
。
接著這樣來啟動 Web 伺服器:
其中 ReactorHttpHandlerAdapter
只是一個包裝了HttpHandler
的 Netty 中的類,其餘的代碼非常簡單直白。我們創建一個新的 Web 伺服器,監聽 localhost 地址的8080埠,並且添加我們的 HTTP handler,實際上這是我們的請求路由器的入口。
好了!整個應用程序已經差不多了,完整的代碼如下:
最後一行只是用來保持 JVM 進程一直運行。 你可能會發現整個應用程序啟動飛快,這是因為沒有任何組件掃描或配置注入發生,就像以前你們使用 Spring 會遇到的。
同時整個程序可以作為一個簡單的 Java 應用程序來運行,不需要任何容器。
為了將整個應用打包和部署,我們仍然可以利用 Spring Maven 插件,只需執行以下操作:
此命令將生成一個包含所有依賴關係的 fat jar,可以在僅安裝了 JRE 的環境來部署和執行:
另外,如果我們想查看整個應用的內存使用情況,大概只有32MB左右,包括了22MB的 metaspace(你們知道用來存放載入的 classes)和大約10MB的 heap。就像前面提到的,整個框架和運行時環境只需要很少的資源。
支持JSON在上面的示例中,我們返回一個字元串作為響應,但是想返回 JSON 對象也非常容易。
讓我們創建一個新的可以返回 JSON 的 API endpoint 來擴展我們的應用。這個 data class 非常簡單,只有一個名為 name
的字元串類型的欄位。為了避免寫那些冗長的 Java 樣板代碼(就像你們厭惡的setter
,getter
),我們使用Project Lombok
特性:使用@Data
註解。通過在類上添加此註解,我們可以透明得獲得getter
,setters
,equals
和hashCode
方法,而無須手動實現。
然後,我們需要擴展我們的請求路由器,以便為 "/json"
路徑的 GET 請求提供新的響應。 這可以通過在現有路由上調用andRoute(...)
方法來完成。
我們還優化了一點代碼,將新的返回 JSON 的 handler 以內連的方式聲明,同時將 ok
靜態導入,這使得代碼變得更簡潔。
重新啟動後,應用程序將通過 "/json"
路徑返回{"name": "world"}
,同時將響應頭部中的內容類型(content-type)設置為application/json
。
你可能已經注意到整個代碼中並沒有定義應用上下文(Application Context)。是的,我們不再需要它!Spring WebFlux 中支持 RouterFunction
,這樣一個簡單且輕量的 JSON 服務不再需要應用上下文。
為了測試 reactive web application,Spring 提供了新的名為 WebTestClient
的客戶端(類似於MockMvc
)。 我們將它綁定到我們的請求路由器上:
WebTestClient 有一組針對
返回結果的斷言,以驗證返回狀態碼,返回體,以及內容類型等等。
總結
Spring 5 引入了新的編程範式用來開發小型的、輕量級的、微服務式 Web應用程序。 我們顯式得定義請求路由器和請求處理函數,在完全不需要應用上下文的情況下快速運行並部署。
代碼本文中所有代碼均可以在這裡訪問到。
https://github.com/alek-sys/spring-functional-microframework
參考https://spring.io/blog/2016/09/22/new-in-spring-5-functional-web-framework
https://spring.io/blog/2016/06/13/notes-on-reactive-programming-part-ii-writing-some-code
http://www.baeldung.com/spring-5-functional-web
https://spring.io/blog/2016/07/28/reactive-programming-with-spring-5-0-m1
※程序員如何提問面試官?針對工程師、技術經理及CTO的提問指南
※Elasticsearch前沿:ES 5.x改進詳解與ES6展望
※如何構建日請求數十億次高性能高可用廣告系統:微博廣告架構解密
※快報|Nginx在Web伺服器市場份額達到33.3%,而Apache則低於50%
※同行越做越複雜,聊聊我們簡化版Twitter的架構:僅原生版3%大小
TAG:高可用架構 |
※袋鼠皮AG的新選擇 Umbro Speciali Eternal Pro AG
※Shannon:如果《Kpop Star6》Casting成功?會選擇YG
※Shannon:Shannon:如果《Kpop Star6》Casting成功?會選擇YG
※鞋履新選擇Malone Souliers
※無鞋帶新選擇 Under Armour Spotlight Pro足球鞋曝光
※Wacom發布Bamboo Sketch手寫筆:非iPad Pro用戶的選擇
※更多BOOST選擇!adidas Originals Iniki Runner BOOST
※Java 之外的選擇,Google 宣布 Kotlin 成為 Android 官方開發語言
※Chanel、LV、Saint Laurent三大包包大PK,你會選擇誰家的?
※買口紅除了Tom Ford和YSL,你還可以選擇Charlotte Tilbury
※因為Supreme x Michael Jackson開售,其他緊鄰門店選擇今日歇業
※Raf Simons 透露自己離開 Dior 並選擇加入 Calvin Klein 真正原因
※還在搶KAWS的聯名款嗎?Public School x Air Jordan XV也許會是你的下個選擇
※Spark與Mavic如何選擇?Spark動手試玩
※According to your astrological sign:根據你的星座,選擇最適合自己的婚紗系列
※外出旅行新選擇 My Passport Wireless Pro無線硬碟體驗
※這款小清新的Air Force 1 Retro PRM Jewel 足以成為您炎炎夏日的不二選擇!
※How to choose your beauty salon?如何選擇美容院?
※聯想ThinkPad X1 Family 2017國內發布,商務新選擇