近幾年,微服務(wù)架構(gòu)迅速在整個技術(shù)社區(qū)竄紅,它被認為是IT軟件架構(gòu)的未來方向,大神Martin Fowler也給微服務(wù)極高的評價。那為什么我們需要微服務(wù),微服務(wù)的真正優(yōu)勢到底是什么,一個完整的微服務(wù)系統(tǒng),應(yīng)該包含哪些功能,本文作者劉彥夫在軟件設(shè)計和開發(fā)領(lǐng)域有10多年工作經(jīng)驗,他將會從他的角度給出答案。
對微服務(wù)的基本理解
顧名思義,微服務(wù)要從兩個方面來理解,一個是“微”,一個是“服務(wù)”。體型小到一定程度才能叫“微”,這個程度是什么呢?一個身高1米6,體重90斤的MM,我們說她苗條。微服務(wù)也一樣,根據(jù)亞馬遜CEO Bezos給出的有趣定義,單個微服務(wù)的設(shè)計、開發(fā)、測試和運維的所有人加在一起吃飯,只需要兩個批薩就夠了,這是就是著名的two pizza team rule。
具備什么樣的能力才能算是“服務(wù)”?這個話題很大,我這里按照自己的片面理解總結(jié)一下,所謂服務(wù)就一定會區(qū)別于系統(tǒng)的功能,服務(wù)是一個或者一組相對的較小且獨立的功能單元,是用戶可以感知的功能最小集,比如:購物車,訂單,信用卡結(jié)算等都可以作為單個服務(wù)獨立提供。
這個理解顯然不夠深刻,為了進一步理解為什么微服務(wù)在近兩年業(yè)界迅速竄紅,理解為什么微服務(wù)會被認為是IT軟件架構(gòu)的未來方向,就要理解為什么我們需要微服務(wù)?它能給企業(yè)帶來什么價值。傳統(tǒng)企業(yè)的IT軟件大多都是各種獨立系統(tǒng)的堆砌,這些系統(tǒng)的問題總結(jié)來說就是擴展性差,可靠性不高,維護成本高。后來有了一個叫SOA的軟件架構(gòu)專門針對這些問題給出了一套解決方案,很多企業(yè)也因此將自身IT系統(tǒng)遷移到SOA架構(gòu)上。
但是,由于SOA早期均使用了總線模式,這種總線模式是與某種技術(shù)棧強綁定的,比如:J2EE。這導(dǎo)致很多企業(yè)的遺留系統(tǒng)很難對接,切換時間太長,成本太高,新系統(tǒng)穩(wěn)定性的收斂也需要一些時間。最終SOA開起來很美,但卻成為了企業(yè)級奢侈品,中小公司都望而生畏。
依然SOA
微服務(wù),從本質(zhì)意義上看,還是SOA架構(gòu)。但內(nèi)涵有所不同,微服務(wù)并不綁定某種特殊的技術(shù),在一個微服務(wù)的系統(tǒng)中,可以有Java編寫的服務(wù),也可以有Python編寫的服務(wù),他們是靠Restful架構(gòu)風格統(tǒng)一成一個系統(tǒng)的。
最粗淺的理解就是將微服務(wù)之間的交互看作是各種字符串的傳遞,各種語言都可以很好的處理字符串,所以微服務(wù)本身與具體技術(shù)實現(xiàn)無關(guān),擴展性強。另一個不同是微服務(wù)架構(gòu)本身很輕,底層也有類似于SOA的總線,不過非常輕薄,現(xiàn)在看到的就兩種方式:MQ和HTTP,而HTTP都不能完全等同于總線,而僅僅是個信息通道。
所以,基于這種簡單的的協(xié)議規(guī)范,無論是兼容老舊系統(tǒng),還是上線新業(yè)務(wù),都可以隨著時代的步伐,滾動升級。比如:你去年還在使用.NET技術(shù),今年就可以平滑的過度到Go了,而且系統(tǒng)已有服務(wù)不用改動。所以微服務(wù)架構(gòu),既保護用戶已有投資,又很容易向新技術(shù)演進。
微服務(wù)水下的冰山
人月不是銀彈,微服務(wù)更不是銀彈,好像軟件微服務(wù)化了,軟件系統(tǒng)就能夠應(yīng)對各種問題了。其實微服務(wù)的水面下藏著巨大的冰山。下面是微服務(wù)提供的能力,以及背后需要付出的代價。
單個微服務(wù)代碼量小,易修改和維護。但是,系統(tǒng)復(fù)雜度的總量是不變的,每個服務(wù)代碼少了,但服務(wù)的個數(shù)肯定就多了。就跟拼圖游戲一樣,切的越碎,越難拼出整幅圖。一個系統(tǒng)被拆分成零碎的微服務(wù),最后要集成為一個完整的系統(tǒng),其復(fù)雜度肯定比大塊的功能集成要高很多。
單個微服務(wù)數(shù)據(jù)獨立,可獨立部署和運行。雖然微服務(wù)本身是可以獨立部署和運行的,但仍然避免不了業(yè)務(wù)上的你來我往,這就涉及到要對外通信,當微服務(wù)的數(shù)量達到一定量級的時候,如何提供一個高效的集群通信機制成為一個問題。
單個微服務(wù)擁有自己的進程,進程本身就可以動態(tài)的啟停,為無縫升級的打好了基礎(chǔ),但誰來啟動和停止進程,什么時機,選擇在哪臺設(shè)備上做這件事情才是無縫升級的關(guān)鍵。這個能力并不是微服務(wù)本身提供的,而是需要背后強大的版本管理和部署能力。
多個相同的微服務(wù)可以做負載均衡,提高性能和可靠性。正是因為相同微服務(wù)可以有多個不同實例,讓服務(wù)按需動態(tài)伸縮成為可能,在高峰期可以啟動更多的相同的微服務(wù)實例為更多用戶服務(wù),以此提高響應(yīng)速度。同時這種機制也提供了高可靠性,在某個微服務(wù)故障后,其他相同的微服務(wù)可以接替其工作,對外表現(xiàn)為某個設(shè)備故障后業(yè)務(wù)不中斷。同樣的道理,微服務(wù)本身是不會去關(guān)心系統(tǒng)負載的,那么什么時候應(yīng)該啟動更多的微服務(wù),多個微服務(wù)的流量應(yīng)該如何調(diào)度和分發(fā),這背后也有一套復(fù)雜的負載監(jiān)控和均衡的系統(tǒng)在起作用。
微服務(wù)可以獨立部署和對外提供服務(wù),微服務(wù)的業(yè)務(wù)上線和下線是動態(tài)的,當一個新的微服務(wù)上線時,用戶是如何訪問到這種新的服務(wù)?這就需要有一個統(tǒng)一的入口,新的服務(wù)可以動態(tài)的注冊到這個入口上,用戶每次訪問時可以從這個入口拿到系統(tǒng)所有服務(wù)的訪問地址,類似于到餐廳吃飯,新菜要寫到“菜單”中,以供用戶選擇。這個統(tǒng)一的系統(tǒng)入口并不是微服務(wù)本身的一部分,所以這種能力需要系統(tǒng)單獨提供。
還有一些企業(yè)級關(guān)注的系統(tǒng)問題,比如,安全策略如何集中管理?系統(tǒng)故障如何快速審計和跟蹤到具體服務(wù)?整個系統(tǒng)狀態(tài)如何監(jiān)控?服務(wù)之間的依賴關(guān)系如何管理?等等這些問題都不是單個微服務(wù)考慮的范疇,而需要有一個系統(tǒng)性的考慮和設(shè)計,讓每個微服務(wù)都能夠按照系統(tǒng)性的要求和約束提供對應(yīng)的安全性,可靠性,可維護性的能力。
綜上所述,微服務(wù)關(guān)鍵其實不僅僅是微服務(wù)本身,而是系統(tǒng)要提供一套基礎(chǔ)的架構(gòu),這種架構(gòu)使得微服務(wù)可以獨立的部署、運行、升級,不僅如此,這個系統(tǒng)架構(gòu)還讓微服務(wù)與微服務(wù)之間在結(jié)構(gòu)上“松耦合”,而在功能上則表現(xiàn)為一個統(tǒng)一的整體。這種所謂的“統(tǒng)一的整體”表現(xiàn)出來的是統(tǒng)一風格的界面,統(tǒng)一的權(quán)限管理,統(tǒng)一的安全策略,統(tǒng)一的上線過程,統(tǒng)一的日志和審計方法,統(tǒng)一的調(diào)度方式,統(tǒng)一的訪問入口等等。
這些系統(tǒng)性的功能也需要有一些服務(wù)來提供,這些服務(wù)不會直接呈現(xiàn)給最終用戶,也就是微服務(wù)系統(tǒng)冰山下面的部分,我們可以簡稱它為微服務(wù)系統(tǒng)的“底座”。所有的微服務(wù)都像一個APP,插在這個底座的上面,享受這個底座提供的系統(tǒng)能力比如:元數(shù)據(jù)存放、灰度發(fā)布、藍綠部署等等。
微服務(wù)系統(tǒng)底座
一個完整的微服務(wù)系統(tǒng),它的底座最少要包含以下功能:
日志和審計,主要是日志的匯總,分類和查詢
監(jiān)控和告警,主要是監(jiān)控每個服務(wù)的狀態(tài),必要時產(chǎn)生告警
消息總線,輕量級的MQ或HTTP
注冊發(fā)現(xiàn)
負載均衡
部署和升級
事件調(diào)度機制
資源管理,如:底層的虛擬機,物理機和網(wǎng)絡(luò)管理
以下功能不是最小集的一部分,但也屬于底座功能:
認證和鑒權(quán)
微服務(wù)統(tǒng)一代碼框架,支持多種編程語言
統(tǒng)一服務(wù)構(gòu)建和打包
統(tǒng)一服務(wù)測試
微服務(wù)CI/CD流水線
服務(wù)依賴關(guān)系管理
統(tǒng)一問題跟蹤調(diào)試框架,俗稱調(diào)用鏈
灰度發(fā)布
藍綠部署
令人困惑的幾個問題
微服務(wù)的底座是不是必須的?
是的,基本上是必須的。你可以不用代碼實現(xiàn)一個資源管理服務(wù),可以手工用Excel管理你的所有機器資源,但是不代表微服務(wù)系統(tǒng)沒有這個功能,只不過這個功能是人工實現(xiàn)的。再舉個例子,日志系統(tǒng)如果只是簡單的打印文件,那么多個微服務(wù)的日志就需要手工收集,人工分類和篩選。所以,微服務(wù)的底座最小集一定會存在,問題是看怎樣實現(xiàn)它。
這里僅僅是總結(jié)了對微服務(wù)系統(tǒng)的基本理解,而實現(xiàn)這個架構(gòu)有很多技術(shù),這里不進行詳細展開。實踐方面,推薦王磊的《微服務(wù)架構(gòu)與實踐》,他描述了使用Ruby相關(guān)的技術(shù)實現(xiàn)了一整套微服務(wù)系統(tǒng),特別是書中后面的實踐部分講解了如何將已有的系統(tǒng)演化為微服務(wù)架構(gòu),是很好的參考和指導(dǎo)材料。
是不是所有軟件都能做微服務(wù)?
這個命題有些微妙,也很難說清楚,回答這個命題本身就是一種挑戰(zhàn),可能最終也沒有正確答案。不過,我還是把我自己的理解寫在這里,讓大家去拍磚。在我這里,答案是否定的。我只需舉出一個反例,比如:存儲系統(tǒng),其架構(gòu)是傳統(tǒng)的分層架構(gòu),每一層都使用下面一層的服務(wù),并為上一層提供服務(wù)。雖然可以將這種架構(gòu)調(diào)整為基于服務(wù)的架構(gòu),但沒辦法做成微服務(wù)。
區(qū)別在哪里呢?核心的區(qū)別在于獨立性上,微服務(wù)大多是可以獨立的運行和使用的,而存儲這種非常底層和基礎(chǔ)的系統(tǒng),每層部件都不能單獨被使用,比如:Pool管理、CHUNK管理、VOL管理、NFS文件系統(tǒng),這些功能都無法離開另外一些功能而獨立運行,要對外提供可用的存儲功能,一大堆功能必須一起上。這種系統(tǒng)做到極致,最多也就能夠使其部件可以獨立的部署和升級,俗稱打熱補丁。
這也就是為什么這種底層傳統(tǒng)系統(tǒng)架構(gòu)通常是單塊架構(gòu)的原因。由于單塊架構(gòu)的各個部分調(diào)用關(guān)系緊密,做成微服務(wù)后系統(tǒng)集成成本會大大增加,不僅如此,這樣的架構(gòu)做成微服務(wù)并不能提高交付效率,因為各個部分根本就無法獨立的運行和測試。
什么樣的軟件做成微服務(wù)?
能不能做成微服務(wù),取決于四個要素:
小:微服務(wù)體積小,2 pizza團隊。
獨:能夠獨立的部署和運行。
輕:使用輕量級的通信機制和架構(gòu)。
松:為服務(wù)之間是松耦合的。
針對于小、輕、松都是可以通過某些技術(shù)手段達到目的,而獨立的部署和運行,則是和業(yè)務(wù)本身有關(guān)系,如果你這個系統(tǒng)提供的業(yè)務(wù)是貼近最終用戶的,并且這些功能之間的耦合性很小,則微服務(wù)就可以按照業(yè)務(wù)功能本身的獨立性來劃分,則這類系統(tǒng)做成微服務(wù)是非常合適的。如果系統(tǒng)提供的業(yè)務(wù)是非常底層的,如:操作系統(tǒng)內(nèi)核、存儲系統(tǒng)、網(wǎng)絡(luò)系統(tǒng)、數(shù)據(jù)庫系統(tǒng)等等,這類系統(tǒng)都偏底層,功能和功能之間有著緊密的配合關(guān)系,如果強制拆分為較小的服務(wù)單元,會讓集成工作量急劇上升,并且這種人為的切割無法帶來業(yè)務(wù)上的真正的隔離,所以無法做到獨立部署和運行,也就更加無法做到真正的微服務(wù)了。
感謝郭蕾對本文的審校。
給InfoQ中文站投稿或者參與內(nèi)容翻譯工作,請郵件至editors@cn.infoq.com。也歡迎大家通過新浪微博(@InfoQ,@丁曉昀),微信(微信號:InfoQChina)關(guān)注我們。