Spring家族很龐大,從最早先出現的服務於企業級程式開發的Core、安全方面的Security、到後來的作為各種資料來源橋樑的Data、最近幾年很火的Boot,以及最新推出的正在蓬勃發展的Cloud(在本文之後都簡單稱為Boot、Cloud省略Spring節省一點我的打字時間)。
上面這個腦圖給出了Spring家族主要的一些成員,右側非Cloud部分列的是功能,左側Cloud部分雖然元件繁雜,但是結構清晰(確實新版本清晰多了,命名也統一,你可以放大圖片看一下這些是否熟悉),所以更進一步列出了元件要的一些模組依賴和開啟功能的主註解。
我說Spring的發展
Spring框架幾乎涉及到了Java企業級服務開發的所有方面,也幾乎針對所有開發常用的模式、中介軟體、資料庫進行了整合適配。
之前在聊網際網路架構模式的時候我談到過,很多時候我們寫一個業務把邏輯寫死寫出來是比較容易的,但是把這個邏輯提取成模式進而打包成一個框架來給大家使用,這是比較難的。因為我們只有經歷過足夠多的場景後才能提取出普適的功能框架,大部分人才能用上,而且我們需要針對核心功能開放出可配置的部分,滿足小部分人進一步定製和擴充套件功能的需要。
Spring框架經歷了幾個階段:
· 第一個階段推出的Core、Security、Data是把單體應用開發服務好。不僅僅提供了便捷的資料庫訪問、Web MVC等必要功能,而且通過AOP、IOC兩大利器讓我們的程式內在能夠做到低耦合可擴充套件。
· 第二個階段推出的Boot的意義不僅僅是加速了開發效率而且能讓我們的程式從可用變為好用,應用程式核心業務邏輯可能只有70%的工作量,要讓程式線上上跑的愉快還有30%的監控日誌打點等工作量需要去做。
· 第三個階段推出的Cloud的意義在於推動了微服務架構的落地。讓不具備開發微服務基礎套件的小型網際網路公司也能享受到免費的開箱即用的微服務解決方案。其實很多人不是看了微服務的架構思想去尋找解決方案,而是瞭解到了Spring Cloud才去瞭解微服務思想從而落地的。
· 目前屬於第四個階段,大力發展Cloud Dataflow+容器。Dataflow的思想是不管是做實時訊息處理的服務還是臨時執行的任務,都可以認為是服務的元件,如果可以有一套DSL來定義這些元件之間的互動方式,然後在容器中進行自由組合、部署、伸縮,那麼架構會非常靈活。下圖是Dataflow管理介面的一個示意圖。
Spring的發展可以看到網際網路架構的發展,Spring給我們帶來相當多的技術啟發,從軟體設計模式的啟發慢慢到了架構的啟發,甚至我覺得Spring是為Java開發打造了架構風格的模板,接下去Spring繼續發展2到3年有望成為架構標準,我在想這個時候應用架構師何去何從?
我說Spring Core
Spring Core提供的IOC、AOP功能已經變為半個Java命根子了。其實很多開發平臺並不是那麼強調IOC和AOP,甚至有的平臺完全沒有相關支援。雖然我一直覺得IOC和AOP是非常好的思想,可以讓我們的軟體內部做到元件之間的低耦合,容易替換,容易擴充套件,但是我的觀點是,作為一個類庫不應該把自己元件的初始化以及組裝工作交給外部來做。我們知道通過IOC容器來管理我們元件的例項化和依賴,其實我們可以在程式內部實現每一個元件,把裝配工作交給XML配置進行,但是對於一些複雜的元件,如果這個工作的配置交給XML進行,那麼也就相當於交給了使用者進行,相當於需要使用者一定要理解元件內部的裝配結構,這是不合理的。更合理的方式是,元件或框架的作者提供一些擴充套件點,讓使用者可以明確通過API來注入自己的擴充套件元件或實現元件,而對於只需要簡單使用元件的使用者可以無需配置開箱即用。
當然,這不是說Spring的IOC和AOP有什麼不好,正因為框架實現的如此靈活,Java使用Spring作為容器也基本是標準了,所以Java界很多框架也因此可以相互進行很好的整合,確實是一個很好的平臺。
Spring 5推出了Reactive非阻塞技術棧,基於Netty或Servlet 3.1+容器,提供了Stream API、WebFlux以及各種響應式的儲存(各種NOSQL)訪問類庫。從前到後實現非阻塞的服務,可以避免IO阻塞佔據執行緒,減少執行緒切換和資源使用,以最小的資源做到最大化的併發。可惜的是JDBC目前並沒有非阻塞的版本,這樣我們主流的基於MySQL的應用並不能進行全鏈路(從Controller到外部的Rest服務到資料庫)的非阻塞IO(一竿子到底這樣才是最爽的)。而且對於Reactive套件,我經過簡單的使用個人感覺API比較晦澀,鏈式呼叫可讀性並不高,而且反而遇到了併發的一些坑,加上程式碼的示例和最佳實踐現在也很少,我感到現在使用並不是特別成熟。
我說Spring Data
Spring Data希望以相對比較一致的Template API來讓我們更方便得使用各種資料儲存。我個人不太喜歡習慣使用Data套件而是更喜歡使用各種NOSQL的Java原生客戶端。幾個原因:
· 原生客戶端緊跟服務端的實現,可以第一時間體驗到最新的功能
· 原生客戶端的API和服務端提供的API往往一一匹配,可以一竿子到底,讓我們功能使用更準確
· 原生客戶端往往只是基於API的簡單封裝,效能更好
當然,如果我們只是對NOSQL進行簡單使用的話,Spring Data可能使用起來更方便。
我說Spring Boot
稍微老一點的Java開發基本都是從純XML配置到XML+註解配置走過來的,比較有意思的是很多開發雖然當初在使用XML配置,但是往往問他們每一個配置的含義都不能準確回答出,基本就是拿著主管或前人搭建的一套XML配置直接複製貼上過來使用。從側面說明了,其實我們大部分那些Mybatis、Spring MVC的配置都是在幹元件初始化而不是定製化的事情。從0開始要讓一個元件用起來就需要這些基本的配置,既然是這樣的話,其實完全可以有預設配置,採用約定大於配置的方式來做。只有在我們需要針對元件進行定製化的時候才去做更多配置。
Spring Boot不但在自動配置、配置簡化上做了很多工作,而且還提供了輕量的嵌入式的容器,只需要20行的Pom+10行程式碼,就可以立即實現一個可以自啟的應用程式(部署簡單)激發了我們使用微服務的熱情。此外也給我們做了很多Production-ready的啟示(Actuator),告訴我們一個完善的應用程式應當注重環境切換、監控、日誌、打點等等方面。總之,之前我們可能需要半天時間搭建一個專案,現在通過start.spring.io甚至只需要10秒。在有Boot之前,我實在沒有興趣使用重量級的Java(可能就為了訪問下資料庫做一些處理,還是使用Python算了)來建立一個實驗性的控制檯應用程式。
我說Spring Cloud
上圖來自官網首頁,很好地闡述了各個元件之間的關係。我們來逐一過一下腦圖上的那些元件:
· 配置管理Cloud Config:提供了客戶端和服務端,客戶端的使用方式和Spring完美結合,服務端提供了Git方式和檔案方式的資料儲存,最新版本也提供了資料庫方式。這個配置管理的功能上和之前《朱曄的網際網路架構實踐心得S1E5:不斷耕耘的基礎中介軟體》一文中我探到的那些配置管理的功能差十萬八千里。
· 服務發現Netflix Euerka:提供可客戶端和服務端(兼管理臺),這裡的客戶端是指服務發現的使用方,其實微服務中的服務在這裡是客戶端。
· 斷路器Netflix Hustrix:提供了客戶端API、聚合服務端Tubine和Dashboard網站。
· 服務閘道器:有Netflix Zuul和Cloud Gateway兩種閘道器可以選擇,後者據說效能更好。閘道器其實就是典型的Filter+Handler的實現機制,通過路由找到合適的Handler,然後呼叫Pre和Post的各種外掛式Filter。
· 呼叫鏈跟蹤Cloud Sleuth:可以搭配Zipkin使用,功能只能說湊活用。Zipkin的那後臺功能上和國內主流網際網路實現的Trace後臺功能相比還是太弱了。
· 訊息驅動Cloud Stream:抽象成為了產出訊息的Source,消費資料的Sink和抓換資料的Processor。然後把Broker的實現通過Binder進行解耦,支援主流的Kafka、KafkaStream和RabbitMQ三種型別。
· 訊息匯流排Cloud Bus:抽象了MQ的功能,支援主流的MQ產品。
· 函式即服務Cloud Function:把函式封裝為Web服務或Stream服務可以獨立呼叫。對函式程式設計的Function、Consumer和Supplier分別對映成為了Processor、Sink和Source。
· 微服務契約Cloud Contract:實現契約優先的程式設計,可以先定義契約對契約進行測試,同時進行服務實現。複雜的服務可以用這套方式來做,消費者提供者對著契約自己編自己的,兩不耽誤。
· 任務框架Cloud Task:非定時任務的概念,這裡的任務是指一次性執行的程式。框架提供了任務執行審計管理最基本的功能。這裡的任務最後可以在Cloud Dataflow中執行也可以獨立執行。
· 管理臺:這裡列的Admin管理臺是第三方提供的,基於Actuator的端點進行資訊的綜合展示和監控。
總結一下,總體上我感覺Cloud模組化的思想很好,模組和模組之間可以相互搭配使用,但是可能一開始沒有進行系統性的規劃,版本的升級帶來的Breaking Changes有點過多,而且因為內容太多了,文件方面沒有特別全面,要全部用起來坑會比較多,需要享受新功能的話還需要不斷更新框架版本不斷踩坑。
從目前功能的完善程度來說我感覺核心功能完善度在60%(大概還需要發展1年可以用的比較舒服)。後臺方面過於簡陋,官方提供的後臺零散醜陋而且完成度極低(相比國內一線網際網路在治理這塊開發的功能來說,完善度大概在30%,大概還需要發展2年可以用的比較舒服,如果可以好好規劃一套完整的後臺把服務治理所有相關功能都整合在一起就好了)。不管怎麼樣,至少Cloud套件是一套完整的解決方案,目前來看還沒有可以媲美的其它開源選擇可以使用(Dubbo我們也知道雖然現在又開始高速迭代,但是由於其原始定位是RPC框架,理念上還是有很多不同的,元件方面並沒有Cloud那麼完善)。
除了功能不完善,Cloud令我擔心的還有一點是(我沒測試過,但是因為看到目前功能的迭代速度對這方面信心不足,誰大規模應用了能否可以給點資料),這些中介軟體(服務發現、閘道器服務、鏈路跟蹤、配置管理)是不是經過壓測,是否可以滿足比較大的壓力,如果只是實現功能的話,可能會在全面用起來後遇到效能瓶頸,在這個時候恐怕就麻煩了。
總結
Spring家族已經是功能強大的龐然大物了,我們的專案pom中出現幾十個Spring依賴也是家常便飯。使用.NET家族的套件也是幾年前的事情了,但是至今我還是覺得微軟.NET的開發套件不管是MVC還是ORM還是RPC方面比Spring的MVC、Data JPA(現在大家都使用Mybatis,Mybatis也還是太弱了)、Cloud套件在功能和設計的優雅上更勝一籌,希望將來可以看到Spring針對這些點繼續發力,並且持續打造Dataflow套件,結合K8S打造成一個微服務的OS(各種中介軟體可以實現一鍵部署叢集)。另外對於Spring Cloud除了核心功能之外,希望在管理臺方面可以繼續完善,打造一個一體化(不一定是一個網站,但是至少可以有許可權控制和審計,實現SSO)的管理臺,全面實現微服務部署伸縮、服務治理、資料流程管理、服務全鏈路監控、配置管理等等功能,也期待Spring Cloud和Dataflow雙劍合璧在將來的2到3年定義微服務和以資料為核心的流處理的架構標準。