微服務的歷史與陷阱
微服務是近幾年非常火熱的架構設計理念,大部分人認為是MartinFlower提出了微服務概念,但事實上微服務概念的歷史要早得多,也不是Martin Flower創造出來的,Martin只是將微服務進行了系統的闡述。不過不能否認Martin在推動微服務火熱起來的作用,微服務能火,Martin功不可沒。
參考維基百科英文版,我們簡單梳理一下微服務的歷史:
2005年:Dr. PeterRodgers在Web ServicesEdge大會上提出了“Micro-Web-Services”的概念。
2011年:一個軟體架構工作組使用了“microservice”一詞來描述一種架構模式。
2012年:同樣是這個架構工作組,正式確定用“microservice”來代表這種架構。
2012年:ThoughtWorks的James Lewis針對微服務概念在QCon San Francisco 2012發表了演講。
2014年:James Lewis和Martin Flower合寫了關於微服務的一篇學術性的文章,詳細闡述了微服務。
由於微服務的理念中也包含了“服務”的概念,而SOA中也有“服務”的概念,我們自然而言地會提出疑問:微服務與SOA是什麼關係,有什麼區別,為何有了SOA還要提微服務?這幾個問題是理解微服務的關鍵,否則如果只是跟風拿來就用,既不會用,也用不好,用了不但沒有效果,反而還可能有副作用
微服務與SOA的關係
對於瞭解過SOA的人來說,第一次看到微服務這個概念肯定會有所疑惑:為何有了SOA還要提微服務呢?等到簡單看完微服務的介紹後,很多人可能就有一個疑惑:這不就是SOA嗎?
關於SOA和微服務的關係和區別,大概分為幾個典型的觀點。
微服務是SOA的實現方式
如下圖所示,這種觀點認為SOA是一種架構理念,而微服務是SOA理念的一種具體實現方法。例如,“微服務就是使用HTTP RESTful協議來實現ESB的SOA”,“使用SOA來構建單個系統就是微服務”“微服務就是更細粒度的SOA”。
微服務是去掉ESB後的SOA
如下圖所示,這種觀點認為傳統SOA架構最廣為人詬病的就是龐大、複雜、低效的ESB,因此將ESB去掉,改為輕量級的HTTP實現,就是微服務。
微服務是一種和SOA相似,但本質上不同的架構理念
如下圖所示,這種觀點認為微服務和SOA只是有點類似,但本質上是不同的架構設計理念。相似點在於下圖中交叉的地方,就是兩者都關注“服務”,都是通過服務的拆分來解決可擴充套件性問題。本質上不同的地方在於幾個核心理念的差異:是否有ESB、服務的粒度、架構設計的目標等。
以上觀點看似都有一定的道理,但都有點差別,到底哪個才是準確的呢?單純從概念上是難以分辨的,我們對比一下SOA和微服務的一些具體做法,再來看看到底哪一種觀點更加符合實際情況。
服務粒度
整體上來說,SOA的服務粒度要粗一些,而微服務的服務粒度要細一些。例如,對一個大型企業來說,“員工管理系統”就是一個SOA架構中的服務;而如果採用微服務架構,則“員工管理系統”會被拆分為更多的服務,比如“員工資訊管理”“員工考勤管理”“員工假期管理”“員工福利管理”等更多服務。
服務通訊
SOA採用了ESB作為服務間通訊的關鍵元件,負責服務定義、服務路由、訊息轉換、訊息傳遞,總體上是重量級的實現。微服務推薦使用統一的協議和格式,例如,RESTful協議、RPC協議,無須ESB這樣的重量級實現。Martin Flower將微服務架構的服務通訊理念稱為“Smart endpoints anddumb pipes”,簡單翻譯為“聰明的終端,愚蠢的管道”。之所以用“愚蠢”二字,其實就是與ESB對比的,因為ESB太強大了,既知道每個服務的協議型別(例如,是RMI還是HTTP),又知道每個服務的資料型別(例如,是XML還是JSON),還知道每個資料的格式(例如,是2017-01-01還是01/01/2017),而微服務的“dumb pipes”僅僅做訊息傳遞,對訊息格式和內容一無所知。
服務交付
SOA對服務的交付並沒有特殊要求,因為SOA更多考慮的是相容已有的系統;微服務的架構理念要求“快速交付”,相應地要求採取自動化測試、持續整合、自動化部署等敏捷開發相關的最佳實踐。如果沒有這些基礎能力支撐,微服務規模一旦變大(例如,超過20個微服務),整體就難以達到快速交付的要求,這也是很多企業在實行微服務時踩過的一個明顯的坑,就是系統拆分為微服務後,部署的成本呈指數上升。
應用場景
SOA更加適合於龐大、複雜、異構的企業級系統,這也是SOA誕生的背景。這類系統的典型特徵就是很多系統已經發展多年,採用不同的企業級技術,有的是內部開發的,有的是外部購買的,無法完全推倒重來或進行大規模的優化和重構。因為成本和影響太大,只能採用相容的方式進行處理,而承擔相容任務的就是ESB。
微服務更加適合於快速、輕量級、基於Web的網際網路系統,這類系統業務變化快,需要快速嘗試、快速交付;同時基本都是基於Web,雖然開發技術可能差異很大(例如,Java、C++、.NET等),但對外介面基本都是提供HTTP RESTful風格的介面,無須考慮在介面層進行類似SOA的ESB那樣的處理。
綜合上述分析,我們將SOA和微服務對比如下表所示。
對 比 維 度 | SOA | 微 服 務 |
服務粒度 | 粗 | 細 |
服務通訊 | 重量級,ESB | 輕量級,例如HTTP/ RESTful |
服務交付 | 慢 | 快 |
應用場景 | 企業級 | 網際網路 |
因此,我們可以看到,SOA和微服務本質上是兩種不同的架構設計理念,只是在“服務”這個點上有交集而已,因此兩者的關係應該是第三種模式。
其實,Martin Flower在他的微服務文章中,已經做了很好的提煉:
In short, the microservice architectural style is an approach to developing asingle application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. |
上述英文的三個關鍵詞分別是:small、lightweight、automated,基本上濃縮了微服務的精華,也是微服務與SOA的本質區別所在。
通過前面的詳細分析和比較,似乎微服務本質上就是一種比SOA要優秀很多的架構模式,那是否意味著我們都應該把架構重構為微服務呢?
其實不然,SOA和微服務是兩種不同理念的架構模式,並不存在孰優孰劣,而只是應用場景不同而已。我們介紹SOA時候提到其產生歷史背景是因為企業的IT服務系統龐大而又複雜,改造成本很高,但業務上又要求其互通,因此才會提出SOA這種解決方案。如果我們將微服務的架構模式生搬硬套到企業級IT服務系統中,這些IT服務系統的改造成本可能遠遠超出實施SOA的成本。
微服務的陷阱
單純從上面的對比來看,似乎SOA一無是處而微服務無所不能,這也導致了很多團隊在實踐時不加思考地採用微服務—既不考慮團隊的規模,也不考慮業務的發展,也沒有考慮基礎技術的支撐,只是覺得微服務很牛就趕緊來實施,以為實施了微服務後就什麼問題都解決了,而一旦真正實施後才發現掉到微服務的坑裡面去了。
我們看一下微服務具體有哪些坑。
服務劃分過細,服務間關係複雜
服務劃分過細,單個服務的複雜度確實下降了,但整個系統的複雜度卻上升了,因為微服務將系統內的複雜度轉移為系統間的複雜度了。
從理論的角度來計算,n個服務的複雜度是n×(n-1)/2,整體系統的複雜度是隨著微服務數量的增加呈指數級增加的。下圖形象了說明了整體複雜度。
粗粒度劃分服務時,系統被劃分為3個服務,雖然單個服務較大,但服務間的關係很簡單;細粒度劃分服務時,雖然單個服務小了一些,但服務間的關係卻複雜了很多。
服務數量太多,團隊效率急劇下降
微服務的“微”字,本身就是一個陷阱,很多團隊看到“微”字後,就想到必須將服務拆分得很細,有的團隊人員規模是5~6個人,然而卻拆分出30多個微服務,平均每個人要維護5個以上的微服務。
這樣做給工作效率帶來了明顯的影響,一個簡單的需求開發就需要涉及多個微服務,光是微服務之間的介面就有6~7個,無論設計、開發,還是測試、部署,都需要工程師不停地在不同的服務間切換。
開發工程師要設計多個介面,開啟多個工程,除錯時要部署多個程式,提測時打多個包。
測試工程師要部署多個環境,準備多個微服務的資料,測試多個介面。
運維工程師每次上線都要操作多個微服務,並且微服務之間可能還有依賴關係。
呼叫鏈太長,效能下降
由於微服務之間都是通過HTTP或RPC呼叫的,每次呼叫必須經過網路。一般線上的業務介面之間的呼叫,平均響應時間大約為50ms,如果使用者的一起請求需要經過6次微服務呼叫,則效能消耗就是300ms,這在很多高效能業務場景下是難以滿足需求的。為了支撐業務請求,可能需要大幅增加硬體,這就導致了硬體成本的大幅上升。
呼叫鏈太長,問題定位困難
系統拆分為微服務後,一次使用者請求需要多個微服務協同處理,任意微服務的故障都將導致整個業務失敗。然而由於微服務數量較多,且故障存在擴散現象,快速定位到底是哪個微服務故障是一件複雜的事情。樣例如下圖所示。
Service C的資料庫出現慢查詢,導致Service C給Service B的響應錯誤,Service B 給Service A的響應錯誤,Service A給使用者的響應錯誤。我們在實際定位時是不會有圖例中這麼清晰的,最開始是使用者報錯,這時我們首先會去查Service A。導致Service A故障的原因有很多,我們可能要花半個小時甚至1個小時才能發現是ServiceB返回錯誤導致的。於是我們又去查Service B,這相當於重複Service A故障定位的步驟……如此迴圈下去,最後可能花費了幾個小時才能定位到是Service C的資料庫慢查詢導致了錯誤。
如果多個微服務同時發生不同型別的故障,則定位故障更加複雜,如下圖所示。
Service C的資料庫發生慢查詢故障,同時Service C到Service D的網路出現故障,此時到底是哪個原因導致了Service C返回Error給Service B,需要大量的資訊和人力去排查。
沒有自動化支撐,無法快速交付
如果沒有相應的自動化系統進行支撐,都是靠人工去操作,那麼微服務不但達不到快速交付的目的,甚至還不如一個大而全的系統效率高。例如:
沒有自動化測試支撐,每次測試時需要測試大量介面。
沒有自動化部署支撐,每次部署6~7個服務,幾十臺機器,運維人員敲shell命令逐臺部署,手都要敲麻。
沒有自動化監控,每次故障定位都需要人工查幾十臺機器幾百個微服務的各種狀態和各種日誌檔案。
沒有服務治理,微服務數量多了後管理混亂
信奉微服務理念的設計人員總是強調微服務的lightweight特性,並舉出ESB的反例來證明微服務的優越之處。但具體實踐後就會發現,隨著微服務種類和數量越來越多,如果沒有服務治理系統進行支撐,微服務提倡的lightweight就會變成問題。主要問題如下。
服務路由:假設某個微服務有60個節點,部署在20臺機器上,那麼其他依賴的微服務如何知道這個部署情況呢?
服務故障隔離:假設上述例子中的60個節點有5個節點發生故障了,依賴的微服務如何處理這種情況呢?
服務註冊和發現:同樣是上述的例子,現在我們決定從60個節點擴容到80個節點,或者將60個節點縮減為40個節點,新增或減少的節點如何讓依賴的服務知道呢?
如果以上場景都依賴人工去管理,整個系統將陷入一片混亂,最終的解決方案必須依賴自動化的服務管理系統,這時我們就會發現,微服務所推崇的“lightweight”,最終也發展成和ESB幾乎一樣的複雜程度。
本文節選自《從零開始學架構:照著做,你也能成為架構師》一書。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31562044/viewspace-2645752/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 微服務1:微服務及其演進史微服務
- CentOS 的歷史與未來CentOS
- Python字典遍歷的陷阱Python
- Flowable查詢歷史任務
- HTTP的歷史HTTP
- Docker與微服務Docker微服務
- 騰訊的歷史
- 微信的歷史
- 也談遊戲與歷史的關係——來自歷史系出身的遊戲研究者的分享遊戲
- 微服務開發的意義 微服務與分散式的關係微服務分散式
- 微服務化的道與術微服務
- 微服務中的Kafka與Micronaut微服務Kafka
- iOS歷史(iOS系統發展歷史)iOS
- 光榮策略遊戲的歷史及未來——歷史篇遊戲
- 容器歷史
- 歷史背景
- tcpdump歷史TCP
- OAuth歷史OAuth
- 分散式與微服務分散式微服務
- 微服務的服務間通訊與服務治理微服務
- 歷史的遺珠:圖靈測試與人工智慧圖靈人工智慧
- Xbox 在日本的複雜歷史與未來規劃
- 聊聊微服務的服務註冊與發現!微服務
- 澳門歷史
- 微服務學習與思考(04):微服務技術體系微服務
- 微服務與架構師微服務架構
- 微服務概覽與治理微服務
- [oracle] 查詢歷史會話、歷史執行計劃Oracle會話
- 信用卡的歷史起源
- Angular Universal 的演進歷史Angular
- 走進資料的歷史
- 服務架構學習與思考(12):從單體架構到微服務架構的演進歷程架構微服務
- 還原歷史?這恰恰是歷史策略遊戲中最難做到的遊戲
- js非同步發展歷史與Promise原理分析JS非同步Promise
- 高效能 MySQL【筆記】-架構與歷史MySql筆記架構
- 批量匯入歷史檔案到日誌服務
- 初識雲端計算:歷史、服務、架構架構
- 通用人工智慧導航:AGI的歷史與現狀人工智慧