《微服務》九大特性筆記
服務元件化
元件,是一個可以獨立更換和升級的單元。就像PC中的CPU、記憶體、顯示卡、硬碟一樣,獨立且可以更換升級而不影響其他單元。
在“微服務”架構中,需要我們對服務進行元件化分解。服務,是一種程序外的元件,它通過http等通訊協議進行協作,而不是傳統元件以嵌入的方式協同工作。服務都獨立開發、部署,可以有效的避免一個服務的修改引起整個系統的重新部署。
打一個不恰當的比喻,如果我們的PC元件以服務的方式構建,我們只維護主機板和一些必要外設之後,計算能力通過一組外部服務實現,我們只需要告訴PC我們從哪個地址來獲得計算能力,通過服務定義的計算介面來實現我們使用過程中的計算需求,從而實現CPU元件的服務化。這樣我們原本複雜的PC服務得到了更輕量化的實現,我們甚至只需要更換服務地址就能升級我們PC的計算能力。
按業務組織團隊
當我們開始決定如何劃分“微服務”時,通常也意味著我們要開始對團隊進行重新規劃與組織。按以往的方式,我們往往會以技術的層面去劃分多個不同的團隊,比如:DBA團隊、運維團隊、後端團隊、前端團隊、設計師團隊等等。若我們繼續按這種方式組織團隊來實施“微服務”架構開發時,當有一個有問題需要更改,可能是一個非常簡單的變動,比如:對人物描述增加一個欄位,這就需要從資料儲存開始考慮一直到設計和前端,雖然大家的修改都非常小,但這會引起跨團隊的時間和預算審批。
在實施“微服務”架構時,需要採用不同的團隊分割方法。由於每一個微服務都是針對特定業務的寬棧或是全棧實現,既要負責資料的持久化儲存,又要負責使用者的介面定義等各種跨專業領域的職能。因此,面對大型專案時候,對於微服務團隊拆分更加建議按業務線的方式進行拆分,一方面可以有效減少服務內部修改所產生的內耗;另一方面,團隊邊界可以變得更為清晰。
做“產品”的態度
實施“微服務”架構的團隊中,每個小團隊都應該以做產品的方式,對其產品的整個生命週期負責。而不是以專案的模式,以完成開發與交付並將成果交接給維護者為最終目標。
開發團隊通過了解服務在具體生產環境中的情況,可以增加他們對具體業務的理解,比如:很多時候一些業務中發生的特殊或異常情況,很可能產品經理都並不知曉,但細心的開發者很容易通過生產環境發現這些特殊的潛在問題或需求。
所以,我們需要用做“產品”的態度來對待每一個“微服務”,持續關注服務的運作情況,並不斷地分析幫助使用者來提升業務功能。
智慧端點與啞管道
在單體應用中,元件間直接通過函式呼叫的方式進行互動協作。而在“微服務”架構中,服務由於不在一個程序中,元件間的通訊模式發生了改變,若僅僅將原本在程序內的方法呼叫改成RPC方式的呼叫,會導致微服務之間產生繁瑣的通訊,使得系統表現更為糟糕,所以,我們需要更粗粒度的通訊協議。
在“微服務”架構中,通常會使用這兩個服務呼叫方式:
第一種,使用HTTP協議的RESTful API或輕量級的訊息傳送協議,來實現資訊傳遞與服務呼叫的觸發。
第二種,通過在輕量級訊息總線上傳遞訊息,類似RabbitMQ等一些提供可靠非同步交換的結構。
在極度強調效能的情況下,有些團隊會使用二進位制的訊息傳送協議,例如:protobuf。即使是這樣,這些系統仍然會呈現出“智慧端點和啞管道”的特點,為了在易讀性與高效性之間取得平衡。當然大多數Web應用或企業系統並不需要作出在這兩者間做出選擇,能夠獲得易讀性就已經是一個極大的勝利了。
——Martin Fowler
去中心化治理
當我們採用集中化的架構治理方案時,通常在技術平臺上都會做同一的標準,但是每一種技術平臺都有其短板,這會導致在碰到短板時,不得不花費大力氣去解決,並且可能還是因為其底層原因解決的不是很好。
在實施“微服務”架構時,通過採用輕量級的契約定義介面,使得我們對於服務本身的具體技術平臺不再那麼敏感,這樣我們整個“微服務”架構的系統中的元件就能針對其不同的業務特點選擇不同的技術平臺,終於不會出現殺雞用牛刀或是殺牛用指甲鉗的尷尬處境了。
不是每一個問題都是釘子,不是每一個解決方案都是錘子
去中心化管理資料
我們在實施“微服務”架構時,都希望可以讓每一個服務來管理其自有的資料庫,這就是資料管理的去中心化。
在去中心化過程中,我們除了將原資料庫中的儲存內容拆分到新的同平臺的其他資料庫例項中之外(如:把原本儲存在MySQL中的表拆分後,儲存多幾個不同的MySQL例項中),也可以針對一些具有特殊結構或業務特性的資料儲存到一些其他技術的資料庫例項中(如:把日誌資訊儲存到MongoDB中、把使用者登入資訊儲存到Redis中)。
雖然,資料管理的去中心化可以讓資料管理更加細緻化,通過採用更合適的技術來讓資料儲存和效能達到最優。但是,由於資料儲存於不同的資料庫例項中後,資料一致性也成為“微服務”架構中急需解決的問題之一。分散式事務的實現,本身難度就非常大,所以在“微服務”架構中,我們更強調在各服務之間進行“無事務”的呼叫,而對於資料一致性,只要求資料在最後的處理狀態是一致的效果;若在過程中發現錯誤,通過補償機制來進行處理,使得錯誤資料能夠達到最終的一致性。
基礎設施自動化
近年來雲端計算服務與容器化技術的不斷成熟,運維基礎設施的工作變得越來越不那麼難了。但是,當我們實施“微服務”架構時,資料庫、應用程式的個頭雖然都變小了,但是因為拆分的原因,數量成倍的增長。這使得運維人員需要關注的內容也成倍的增長,並且操作性任務也會成倍的增長,這些問題若沒有得到妥善的解決,必將成為運維人員的噩夢。
所以,在“微服務”架構中,請務必從一開始就構建起“持續交付”平臺來支撐整個實施過程,該平臺需要兩大內容,不可或缺:
自動化測試:每次部署前的強心劑,儘可能的獲得對正在執行軟體的信心。
自動化部署:解放繁瑣枯燥的重複操作以及對多環境的配置管理。
容錯設計
在單體應用中,一般不存在單個元件故障而其他還在執行的情況,通常是一掛全掛。而在“微服務”架構中,由於服務都執行在獨立的程序中,所以是存在部分服務出現故障,而其他服務都正常執行的情況,比如:當正常運作的服務B呼叫到故障服務A時,因故障服務A沒有返回,執行緒掛起開始等待,直到超時才能釋放,而此時若觸發服務B呼叫服務A的請求來自服務C,而服務C頻繁呼叫服務B時,由於其依賴服務A,大量執行緒被掛起等待,最後導致服務A也不能正常服務,這時就會出現故障的蔓延。
所以,在“微服務”架構中,快速的檢測出故障源並儘可能的自動恢復服務是必須要被設計和考慮的。通常,我們都希望在每個服務中實現監控和日誌記錄的元件,比如:服務狀態、斷路器狀態、吞吐量、網路延遲等關鍵資料的儀表盤等。
演進式設計
通過上面的幾點特徵,我們已經能夠體會到,要實施一個完美的“微服務”架構,需要考慮的設計與成本並不小,對於沒有足夠經驗的團隊來說,甚至要比單體應用發付出更多的代價。
所以,很多情況下,架構師們都會以演進的方式進行系統的構建,在初期系統以單體系統的方式來設計和實施,一方面系統體量初期並不會很大,構建和維護成本都不高。另一方面,初期的核心業務在後期通常也不會發生巨大的改變。隨著系統的發展或者業務的需要,架構師們會將一些經常變動或是有一定時間效應的內容進行“微服務”處理,並逐漸地將原來在單體系統中多變的模組逐步拆分出來,而穩定不太變化的就形成了一個核心“微服務”存在於整個架構之中。