工程師們不斷推動下的雲服務架構

ITPUB社群發表於2022-11-21


一、工程師們超越時代的應用架構設計之美


記得自己在2003年把握住了寶貴的面試機會,成為了一名Java程式設計師,那個時候我參與的專案還在使用JSP,Servlet,JavaBeans和JDBC所組合的最原始的Web應用框架,Spring framework的流行還要等到兩年以後。

作為原始的應用框架,如果是一位牛逼的資深級程式設計師,一定能寫出最整齊、簡潔與極致高效能的程式碼,但是對於需要更多人參與進來的軟體工程來講,原始的框架很容易導致混亂,因此各種Web架構總是被頂尖的工程師們不斷更新迭代,推陳出新,引導大眾工程師們去關注業務本身而非瑣碎的技術問題。

然而在那個IT時代,奔騰CPU尚在,還是32位作業系統的天下,記憶體普遍不超過2GB,區域網的頻寬還是10M/100M自適應的水平,若要工程師參與的專案不去關注瑣碎的技術,不去操心底層服務,只關注業務本身,在當時其實有些不可思議的事情。

但是工程師們對科技生產力提升的嘗試遠遠超出了我們的想象,EJB(Enterprise Java Beans)技術作為超越時代的分散式應用架構設計,就在我們入行的時候被廣泛應用與嘗試,儘管2.0版本的嘗試最終失敗了,還催生出了更偉大與流行的Spring框架。

但是我們重新翻看那一段歷史,只是為了欣賞那種企業級應用的分散式架構之美,欽佩天才般的科學家和IT工程師們的創造力以及對於未知領域的勇敢嘗試。

什麼是EJB呢? 構件用於封裝業務邏輯,使開發人員無須再操心資料庫訪問、分散式事務處理、安全性、多執行緒併發問題等瑣碎任務的程式設計,這是在1998年提出了來的架構設計,在2001年2.0版本的釋出後,已經在全世界的範圍進行了廣泛嘗試。這種目標理念就算放到現在也一點都不過時,有時候我們不得不感慨,後人只是不斷實踐與最佳化前人所提出的設想。

而我在2004年也在使用EJB2.1版本曾參與開發了ERP系統,實際上並不成功,EJB自身在部署方面的臃腫,實體Bean在分散式環境下的極低效能,導致了工程最終不能如期交付,而且專案中解決技術實施複雜性所花費的精力遠遠超過了解決業務自身的問題。

最終在《Expert one on one J2EE development without EJB》,Spring之父那本去EJB的經典之作出版後,隨著Spring IOC、AOP技術配合Hibernate形成了的巨大沖擊下,EJB所構建的分散式理想徹底垮塌。

如下圖1 EJB3應用架構示例所示:

工程師們不斷推動下的雲服務架構

1 EJB3應用架構示例

這是我在2010年參與的一個電商專案所抽離出了分散式應用架構的一部分應用案例,這時候已經開始應用EJB 3.0,部署在雲端跨區域的兩臺AWS EC2虛擬節點,分別管理著各自的Amazon RDS資料庫。

使用者有可能使用獨立安裝在作業系統上的軟體,也可能使用瀏覽器透過Web訪問,例如:訂單邏輯進行業務邏輯元件化以後透過遠端(Remote)或本地(Local)的釋出,就輕鬆應對了不同客戶端的需求,這種RMI(遠端方法呼叫)與目前流行的Http協議的Restful風格架構走了完全不同的兩種風格。

訂單在呼叫支付元件的過程實際上是進行了一次中介軟體支援的分散式事務的操作(JTA事務),透過這種手段,實現了不同網路區域的雙庫資料的兩階段事務提交與回滾。

如果從架構圖中看,這種分散式架構中每個EJB業務元件都是獨立部署在一個上下文容器中執行,透過網路互相通訊與協作,難道它不夠優雅嗎?但為什麼最終還是無法成為行業主流而逐漸沒落呢?這其實是我們思考的關鍵。

分散式架構的複雜性在當時是非常重要的原因,但我認為更關鍵的原因在於中介軟體服務的依賴性遠大於Spring生態,這些中介軟體服務其實就是一些廠商根據JavaEE規範所提供的中介軟體服務產品,例如:JBoss、Glassfish等。

我們可以看到Spring框架IOC、AOP技術,後來發展出SpringBoot、SpringCloud,本質上都是在簡化應用所依託的中介軟體服務。

這樣對於開發者來講,在整個開發過程會更為靈活與自由,輸出的軟體系統也更加與平臺無關。

從這裡就能看到一種是流行的趨勢,那就是無服務化(serverless)的趨勢,本質上就是在不斷解放開發者的生產力,然而基於JavaEE規範的EJB儘管經歷了三代的變革,但其本質仍然是重度依賴有服務的環境,因此儘管EJB的分散式架構設計超前了二十年,但仍然因其不適應技術潮流而被逐漸淘汰掉。


二、當今微服務、分散式和容器技術的演進融合


隨著以Amazon為首的雲端計算平臺在IT基礎架構中扮演著越來越重要的角色,工程師們主要談論的Web應用架構也逐步提升為雲服務架構,這時候我們已經進入到了雲時代,那麼曾經叱吒風雲的JavaEE規範生態與大多數中介軟體供應商逐漸被雲平臺所替代,在雲平臺之上則是更為輕量化的微服務架構與容器化技術承載了主流的雲應用專案的執行。

但是分散式架構並沒有停止腳步,而且在軟體架構中變得越來越核心,為什麼分散式會越來越重要呢?其實在上面我們提到的EJB架構已經在二十年前就開始了分散式的嘗試,只不過那個時候摩爾定律依然有效,軟體系統在單機部署和執行會更加的穩固,分散式更多是以雙機熱備的形態出現,再加上還沒有千兆甚至萬兆頻寬的普及,分散式的需求並不強烈,效能拉胯也非常明顯。

然而在當下,隨著網際網路的使用者規模化,導致了高併發、大規模資料引發的問題頻生,往往單點故障導致的高可用性會更致命,多路並行提升效能的需求很強烈。另外專案中軟體系統的開發規模也在不斷膨脹,單體架構的軟體,其工程化組織管理必然會隨著長期維護而走向臃腫與混亂。

因此才有了微服務架構的用武之地,微服務具有哪些特點呢?

  • 微服務專注小的個體問題,形成服務,透過鬆耦合的通訊機制協作起來,解決更大的問題

  • 微服務傾向於拆分,也就是將單體應用盡量拆分到一個適當的粒度,形成個人或小團隊去關注獨立的服務個體;

  • 微服務的實施模式是自底向上型:不同的小團隊分配不同的微服務進行開發、構建、部署、釋出。

因此面對上述的難題,微服務架構為開發者開啟了一個更為適度、自由、靈活的新局面,在微服務專案具體實施的過程中,它又與分散式架構緊密結合在一起。

在前幾年的時候,我有機會負責架構設計了網際網路醫療平臺的專案,這個專案就是典型的微服務架構案例。它的特點在於將醫療資訊化的靈魂裝進網際網路的外殼中,因此醫療業務的複雜性與網際網路的技術平臺性需要同時相容。

那麼大量的外部系統需要與平臺對接,甚至頻繁地升級,因此就必須尋求一種架構上的分解,所謂的分而治之,才能保證主體系統不會因為區域性的頻繁變化而變化,而且不同服務具有不同的釋出策略,並由不同的團隊適當地協作完成。

這種多維度的複雜需求疊加,對於單應用架構必然會導致臃腫與遲緩。

如下圖 2 網際網路醫療微服務與分散式架構示例所示:

工程師們不斷推動下的雲服務架構

網際網路醫療微服務與分散式架構示例

我們開發的網際網路醫療平臺被切分成了醫生端、患者端、平臺端等N多個微服務例項所組成。由閘道器對網際網路的不同使用者訪問重定向到不同版本的微服務例項之上,閘道器與微服務之間、微服務與微服務之間、微服務與各個資料分庫之間就形成了一種分散式的拓撲結構,另外承載高併發的關鍵微服務也可以由多例項副本形成均衡負載。

從上圖中的例項我們可以看到微服務模型單元要比過去EJB模型單元更粗粒度,是以服務為基準而非元件,那麼就不會像過去經典JavaEE架構所引發的一種強制性措施,要求更細粒度的元件必須分佈,而是給予架構師更為靈活的自由度,去劃分適合大小的服務粒度並進行適當的分佈。

另外微服務是一種架構指導方法,而不是JavaEE那種強制規範,那麼就不會對開發者硬性規定底層需要依賴什麼樣的服務,這就保證了輸出的軟體具有平臺無關性,也就促進了軟體服務在雲平臺的快速普及。

在這些微服務例項的幕後,其實就有了不同開發團隊、QA人員、運維工程師的共同協作實現系統的釋出升級,這個過程就是對DevOps過程方法的最好實踐。

如下圖3 網際網路醫療平臺微服務的版本升級案例所示:

工程師們不斷推動下的雲服務架構

網際網路醫療平臺微服務的版本升級案例

說到這裡,我們就會覺察到應用軟體架構的發展其實就是不斷追求系統的獨立性與平臺無關性,並且透過分散式不斷增加與均勻算力,透過功能模組拆解不同提升分工效率。

軟體應用架構發展到了微服務這個階段看起來應該很不錯吧,可是並沒有停止工程師們繼續最佳化的腳步,現在又面臨一個問題,那就是採用更多機器組成的分散式網路節點,如何才能最佳化計算資源的使用?

例如:我們在一臺伺服器上想要部署兩個Tomcat服務,其實就等同於作業系統執行了兩個程式,這兩個程式共享系統資源,就會存在資源爭用問題,也會導致一些資源配置上的衝突,尤其是起到相同作用的多組程式。

這時候容器化技術就應運而生,例如:Docker,主要機制之一就是透過Linux的namespace機制實現了資源隔離,你就能在有限的雲資源上跑出很多服務,而且容器作為作業系統上的一個程式,容器之間互不影響,並且可以針對容器的CPU、記憶體等計算資源進行預先分配,簡單一條命令就能部署和執行一個服務。

這樣就極大簡化了服務在雲伺服器上的部署難度,提升了更高的效率,甚至我們可以同時部署多個版本的服務形成生產與測試環境的並存。

如下圖 4 計算節點多容器部署示例所示:

工程師們不斷推動下的雲服務架構

計算節點多容器部署示例

我們在一臺AWS EC2伺服器部署了12個Docker容器,其中有8個是可執行的容器,這就包括了網際網路醫療兩組不同的微服務:生產級與測試級,整個分散式網路的計算節點算下來,大概有50多個容器服務在執行。

為什麼要將生產與測試儘量結合在一起執行呢?

因為我們仔細統計過我們在做網際網路醫療平臺的時候,對接了:分散式物件儲存、簡訊服務、地圖服務、推送服務、多種銀行支付、公眾號與小程式、醫院HIS、Pacs、Lis、...。

若單獨搭建線下的測試環境,那麼測試組最終測出結果與實際生產環境有偏差,總是因為各種外部因素而無法彌合,因此儘量讓開發測試與部署釋出結合的更自然,這也是DevOps逐漸混淆開發、測試、部署與釋出之間界限的精髓所在!

就是因為容器技術的支撐,讓生產環境與測試環境可以無縫結合成為了可能。


三、展望雲服務架構的未來


透過上述各章節的描述,我們可以看到應用服務架構從二十年前JavaEE標準需要重度依賴有服務的時代,逐漸演進到如今Amazon引領的Serverless的時代,這是無數工程師、開源社群和商業公司的共同努力。

那麼我們暢想一下雲服務架構的未來,我認為基於雲平臺的無服務架構應該會成為主流模式,無服務這是讓開發者更加關注業務本身,而非基礎設施與瑣碎的基礎技術。

但是對於開發者來講,無服務的優勢在於叢集化的分散式計算資源的自動排程,那麼分散式架構必然會成為繞不過去的複雜問題,對於分散式架構的複雜特性又會讓很多開發者變得理解艱難,例如:CAP定理、副本機制、分割槽、多路並行、單點故障等等。

因此必然雲服務廠商會在這個方面的基礎設施層進行發力,例如Amazon EKS就是在建立和執行K8s叢集提供了一整套分散式環境下的容器編排的解決方案,目標就是讓開發者不用關注太複雜的分散式問題。

我相信這種去分散式複雜化的基礎設施必將對應用軟體架構起到越來越重要的作用,也會變得越來越流行。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024420/viewspace-2924369/,如需轉載,請註明出處,否則將追究法律責任。

相關文章