Java開發微服務實現分散式架構應用總結

架構大資料雙料架構師發表於2020-10-15

寫在前面

突入其來的新肺炎疫情打亂了節日生活的節奏,沒有能力參與這場危機的社會救援,只能窩在家裡不去給社會添亂了,在此向目前奮戰的抗疫前線的每一位工作者致以崇高的敬意,是你們的勇敢和堅毅撐起了我們這個社會的脊樑!

作為一名工作有年頭了的軟體技術工作者,這個時候也沒什麼可以做到,還是繼續我以前的技術學習思路講解的,希望能給那些跟我一樣宅在家裡,想學習Java程式設計技術提高自己的小夥伴們提高一些可以參考借鑑的知識理解和學習素材。

本文我想從Java開發技術的角度來簡單說一下現在流行的分散式服務架構之微服務實現。我會從過去很多公司已經使用很成熟的巨型單體應用程式架構開始,分析一下其優缺點,然後介紹什麼是分散式架構,以及為什麼選擇微服務來實現分散式架構,其好處有哪些等。

通過本文我想讓初學程式設計技術的小夥伴理解Java技術棧發展到今天,以微服務實現分散式架構應用為什麼成為必須要學習的一個重要技能。同時還希望通過我的描述讓小夥伴們理清Java技術棧發展到今天的脈絡,對其學習的內容有一個更加深刻的理解。

 

Java企業級應用 Java EE和 Spring 框架

在說使用Java技術棧實現分散式微服務架構之前,我們先來簡單瞭解幾個Java學習者經常說的幾個概念,比如Java EE和Spring 框架。

可能很多中途轉入Java技術學習的同學一上手就用Spring 技術棧相關的技術,一說起來就是SSN之類的,基本上沒有注意過Java EE這類的名稱。

這裡我簡單的說一下它們,Java語言最初開發出來是實現能夠脫離作業系統而獨立執行的小的程式碼片段的環境,相當於一個應用程式套,後來隨著Java語言的發展其能開發的應用程式型別已經幾乎覆蓋了所有型別。

程式的應用主流自然是工業企業界,由於各家應用中存在很多共性,所以在開發各自應用時大家會共享一些內容,形成社群規範,開發出很多通用的JAR包和類庫,它們被加入到Java的發行包裡,形成了後來我們知道的Java To Enterprise Endition(J2EE),延續發展到現在新版的成為Java EE。

也就是說Java EE是針對企業開發制定的通用規範和基礎功能實現的合集,它包括了表現,容器,資料持久化,以及網路傳輸等多方面的技術實現和基礎產品。

而現在流行的Spring框架只是實現使用輕量化的容器實現了該規範的一套全新技術組合框架,在開發一套應用程式過程中我們可以選擇使用Java EE規範的其它實現來進行,比如CDI,JPA,JSF, JTA等等,也可以使用Spring 容器和Spring MVC整合Spring 實現JPA的Spring Data套件來進行。

現在由於Spring 社群的出色工作,其輕量級的開發框架和相關技術棧被大部分主流公司接受成為Java企業級開發流行的技術組合。特別是在整合了包管理工具和元件化了web容器後的Spring Boot, 讓Java的企業級應用開發進入了一個前所未有的快捷方便時代。

 

簡單總結來說就是,面對企業級應用開發過程中需要統一標準,比如從表現層,到業務邏輯層,到資料以及資源儲存層涉及到的內容有介面表現技術,Java資料持久化訪問技術,web服務Servlet技術,容器依賴注入技術,還包括Java環境資源命名標識技術,資料庫的連線和訪問技術,檔案儲存和讀取技術等等。

這些Java社群都制定的相應的規範,同時根據這些規範產出了一些通用基礎的元件產品而這些內容共同組合成了一個Java企業級應用開發套件組合JaveEE,而我們熟悉的Spring框架是採用了Spring自己的受託管Bean規範構建的容器來組合各個基礎元件的框架技術。

它是基於Servlet元件上的,更加輕量級,更易於管理和使用。同時強大的Spring社群為我們的開發提供了強大的基礎功能類庫的元件,讓我們可以自己使用它們快速的開發應用。

 

應用程式架構的演化和發展

前面我理解了Java企業級開發的主要技術後,我們來看一下有關應用程式架構的演化和發展。

如果你經歷過從一家企業的創業初期伴隨企業成長到大規模企業集團過程,你就能深切體會到企業應用開發過程中應用程式架構的演變過程。

在企業初期規模比較小,都是為了滿足某個主要功能需要才會去開發應用程式,往往都是獨立的完成某個主要的功能的應用系統。慢慢的隨著企業規模擴大,業務增多需要的功能系統也會增加,會出現各部門都有一套跟自己業務相關的系統,企業的資訊都分儲在這些系統的資料庫裡,形成了早期獨立系統成群的資訊孤島現象。這個階段每個系統基本上都是一個獨立的王國。

由於各個業務部門相互之間有資訊互動的需求,如此開始了系統整合的發展程式。從最初的JMS基礎技術到後來的企業資料匯流排服務以及SOA技術的努力,基本能夠解決企業內部資訊孤島問題,也能夠進化出企業決策資訊支援系統,但是這些技術讓企業的資訊系統成了一個堪比猛獁象身體級別的巨型單體應用。

我們說單體應用一般是指我們部署的程式碼塊包含了過多的業務邏輯元件,也就是說這些業務邏輯元件都執行在同一個系統程式中。

這樣的應用程式絕大部分的開發人員都非常熟悉,因為直到現在除了個別企業外幾乎在所有企業裡都能看得見。而且很多傳統的技術團隊對這類系統的開發管理和維護都輕車熟路了。

 

這類系統的特點是不能隨意因為小需求和小故障而做更新發布,必須要制定有一定時間週期跨度的更新發布計劃。

這種架構不能單獨對其內部某個業務邏輯元件或服務進行單方面的擴容,如果真的需要那麼可能需要大量的甚至冗餘的硬體基礎設施投資。

由於是多個元件服務執行在同一個程式中,很容易讓單個元件的效能降低影響的整個應用程式的效能表現。

而且隨著功能需求的增加,程式碼量會一個版本比一個版本龐大,程式碼實現的複雜度會不止一個數量級的提升。

如果我們起初選擇了某些第三方的軟體裝置,更換難度有可能超乎預期。

關於分散式架構

之所以稱之為分散式,是因為整個應用程式的各功能是由跨越程式或者是跨越網路邊界的多個構成部分構建而成。這些分散式部署的應用程式組成部分可以是RESTful APIs端點,訊息佇列,web服務甚至資料儲存等。

而在巨型單體應用時代,我們在實現分散式部署架構時只是將整個應用的資料儲存部分開部署到其它伺服器上,採用web伺服器,應用伺服器和資料儲存伺服器這樣的類似重複的粗粒度分散式佈局。

現在真正的分散式應用架構,是在應用程式級別上進行元件化設計從而能夠真正做到功能上的分散式架構實現。這種實現裡分散式是應用程式的構成元件跨越程式和網路邊界的分佈佈局。

由此Java開發技術裡的程式間資訊通訊和遠端過程呼叫技術出現發展成熟,不同的部署宿主體之間的通訊則依託於網路技術TCP/IP,在應用邊界層級上我們多采用HTTP協議通訊來實現端點介面RESTful APIs。

這一切同樣是微服務實現分散式架構的基礎。

微服務,我們可以簡單的理解為實現單一功能的執行在單一執行時環境中的元件,其執行的單元是執行時環境。對於Java語言來說是一個JVM,我們可以通過增加JVM來擴充該服務的處理容量和規模。

將這些單一的分散式部署的元件化服務組合起來共同實現整個應用程式的功能,就是一個分散式的微服務架構應用。

這裡說一下一個名詞執行時runtime,其實它是某個應用能夠執行的所有環境所需集合。比如我們的JVM它就是所有Java應用程式賴以執行的基礎環境集合,它包括了宿主機器的環境引數抽象,Java語言編譯處理功能,以及其它基礎的比如時間,編碼等內容處理。

理解微服務實現分散式架構

由此我們可以這麼理解微服務實現分散式架構,就是通過一個個獨立的執行時環境管理的功能單一的應用功能借助規範統一的通訊標準相互連線構成整個應用程式。

這種構成部件都是獨立的執行環境支援的功能服務,它們可能是執行在同一臺主機節點上通過程式間通訊連線的多個JVM程式,也可能是執行在多個主機節點上通過網路間通訊連線的程式。

至於選擇什麼樣的方式要看我們的應用實現是面對外部邊緣介面還是內部元件邊緣介面,如果是對外部使用者提供的服務介面我們一般都會採用基於HTTP的RESTful APIs來實現。如果是對內部元件提供通訊互動的介面我們大多傾向於考慮使用RMI方式。

由於微服務單體的特點是功能單一系統自治以及可以通過叢集化來提供統一的功能服務,所以,微服務實現起來程式碼結構不會過於複雜難於維護,同時由於功能單一,在更新迭代過程中能夠儘量降低對其他功能實現的影響。

這種簡單的統一性,能夠讓我們根據系統需求動態的擴容或者縮減該功能服務的處理能力,同時還能夠進行不同版本的並行執行。這些特點都給企業採用微服務架構帶來足夠大的誘惑力。

但是微服務架構的優勢雖好但是其實現的複雜程度是很多企業不得不考慮的一大現實問題。

微服務實現分散式架構其實就是將傳統的我們在實現應用程式中將所有的業務邏輯元件集合到同一個程式中來通過執行緒之間的通訊來相互連線和呼叫實現整體功能不同,它是將我們的應用程式的功能模組做了垂直方向的切分,將過去線上程之間的通訊從同一個程式中上升到程式之間,使得封裝的邊界從過去的執行緒級別擴充套件至程式級別,如此一來讓每個程式執行的功能元件更單一,對其處理功能的控制更為精確,讓我們可以根據我們應用程式的處理, 能力的需要精確的對某一部分功能進行動態的擴容和縮量。

從執行緒級別的通訊,既變數共享和域內方法呼叫,到程式級別則是遠端方法呼叫或者跨網路節點之間的網路通訊。如此就將遠端過程呼叫和網路通訊的處理技術引入到我們應用程式的功能內元件的內部通訊實現中來。

可以這樣理解,我們將我們傳統的應用放到了網際網路上,使之成為一個真正基於網路的架構實現的應用。但是由於遠端呼叫和網路通訊的特點造成了其實現的成本要遠高於傳統的同一程式內部的執行緒之間通訊。

微服務實現分散式架構基礎

這就需要我們在實現微服務分散式架構的時候,首先要解決遠端點對點或者網路上各個節點計算機之間的通訊控制連線問題。然後是每個微服務元件獨立執行在宿主機器上的環境隔離問題。

因為我們要求的微服務元件儘量做到功能單一,依賴簡單,從而才能更加精確的控制它們。那麼在一臺主機伺服器上只執行單一的元件服務將是極大的浪費,為了充分利用現狀商用計算機的處理能力,我們需要一種技術來對元件服務的執行環境進行隔離封裝,從而更高效的利用硬體資源,這就是虛擬化和容器化技術為我們解決的問題。

有了容器化技術比如Docker,我們就有了輕量級的可執行單個元件服務的虛擬節點,它不同於過去我們重用的虛擬機器技術,虛擬機器被看成是傳統計算機的簡單抽象,因為它沒有擺脫作業系統這個負擔。使得其佔用的資源空間巨大,同時啟動和關閉緩慢,無法滿足微服務架構的要求。

有了Docker這樣輕量級的容器,我們可以通過對Docker容器的管理來抽象我們對元件化服務執行環境的管理。在我們有了眾多的容器執行在服務節點上的時候,新的需求出現了,我們如何去管理眾多的元件服務容器呢?

這就是Kubernetes這樣的軟體要解決的問題,它通過提高對Docker的頂層抽象來對映Docker內部的資源和網路管理介面,來統一協調管理眾多的Docker例項,使之能夠動態的管理眾多的執行節點。

讓這些執行節點一起共同為某個應用服務提供處理能力。

 

微服務的部署執行

微服務實現分散式架構的基礎是網路節點叢集,將過去傳統的單臺伺服器節點完成的所有事情轉變成多個連線的多型服務節點,可能是虛擬的也可能是物理節點。

由於微服務的設計運來聚合在一起的各功能元件現在需要分佈到單個節點上或者一個叢集上。比如之前我們web伺服器自己承擔的訪問路由問題,在微服務元件設計中我們會獨立設計一個閘道器服務元件甚至是閘道器服務叢集。

將其部署到一個獨立的節點或者節點叢集上,以提供專門的閘道器相關的業務,比如身份驗證,鑑權,訪問資料過濾,以及頂層路由業務處理。

同時我們針對應用程式的某個業務邏輯模組服務設計,也可以複製其整體的設計,提供該專項業務訪問的路由層,來統一路由訪問到其各個子節點服務上。

由於我們在設計中考慮到服務的穩定性和彈性要求,我們會使用部署節點叢集來實現各部分功能,這就要求我們能夠對這些叢集節點的執行情況進行監控和管理,通過動態的對節點執行狀態的檢測掌握各個服務元件執行的狀況,以及時的對其進行調整,以保證服務執行穩定性。

同時動態的增加和縮減提供同一服務的執行節點數量應對業務處理流量的波動。這些都需要藉助於我們對所有微服務和節點叢集的動態管理技術。

在設計微服務實現分散式架構應用過程中會遇到事務處理問題,在傳統的單體應用程式設計過程中,我們可以通過在同一程式中多個執行緒的執行控制,以及在資料庫中統一事務提交來處理常見的交易事務問題。

而到了微服務分散式架構狀態下,這些處理方式都已不能滿足事務處理要求,因為這些事務處理將跨越多個程式和資料庫,就很難實現一致的提交和回滾這樣的完整性問題保證了。

為此微服務架構的設計者們提出了補償機制,就是通過事件通訊的方式將所有的操作記錄並可逆執行,通過補償方式來達到資料最終的一致性來解決事務完整性問題。

當然,在設計微服務應用的時候,我們應該儘量的避免產生跨越多個元件服務的事務型業務出現。 相關社群裡也提供了不少有關微服務架構應用程式的事務處理方案,比如通過一個獨立的服務程式來監控所有相關事務的處理情況,以最終決定是否統一提交還是回滾。

總結

總體來說,我們在學習Java技術棧來實現分散式微服務架構應用時,應該首先對分散式架構有一個清晰的理解,同時要了解通訊級別對應的具體實現,理解網路通訊對於現在分散式架構應用的重要作用。

從而從整體上把握關於微服務和分散式架構應用的設計和開發。

最後祝願疫情早日銷退,國泰民安。

相關文章