顯然猜敢,隨著系統(tǒng)復(fù)雜度的提升姑荷,以及對系統(tǒng)擴展性的要求越來越高,微服務(wù)化是一個很好的方向缩擂,但除此之外鼠冕,微服務(wù)還會給我們帶來哪些好處?
獨立胯盯,獨立懈费,還是獨立
我們說微服務(wù)打響的是各自的獨立戰(zhàn)爭,所以陨闹,每一個微服務(wù)都是一個小王國楞捂,這些微服務(wù)跳出了“大一統(tǒng)”(Monolith)王國的統(tǒng)治,開始從各個層面打造自己的獨立能力趋厉,從而保障自己的小王國可以持續(xù)穩(wěn)固的運轉(zhuǎn)寨闹。
首先,在開發(fā)層面君账,每個微服務(wù)基本上都是各自獨立的項目(project)繁堡,而對應(yīng)各自獨立項目的研發(fā)團隊基本上也是獨立對應(yīng),這樣的結(jié)構(gòu)保證了微服務(wù)的并行研發(fā)乡数,并且各自快速迭代椭蹄,不會因為所有研發(fā)都投入一個近乎單點的項目,從而造成開發(fā)階段的瓶頸净赴。開發(fā)階段的獨立绳矩,保證了微服務(wù)的研發(fā)可以高效進行。
服務(wù)開發(fā)期間的形態(tài)玖翅,跟服務(wù)交付期間的形態(tài)原則上是不需要完全高度統(tǒng)一的翼馆,即使我們在開發(fā)的時候都是各自進行割以,但交付的時候還是可以一起交付,不過這不是微服務(wù)的做法应媚。
在微服務(wù)治理體系下严沥,各個微服務(wù)交付期間也是各自獨立交付的,從而使得每個微服務(wù)從開發(fā)到交付整條鏈路上都是獨立進行中姜,這大大加快了微服務(wù)的迭代和交付效率消玄。
服務(wù)交付之后需要部署運行,對微服務(wù)來說丢胚,它們運行期間也是各自獨立的翩瓜。
微服務(wù)獨立運行可以帶來兩個比較明顯的好處,第一個就是可擴展性嗜桌。我們可以快速地添加服務(wù)集群的實例奥溺,提升整個微服務(wù)集群的服務(wù)能力,而在傳統(tǒng) Monolith 模式下骨宠,為了能夠提升服務(wù)能力,很多時候必須強化和擴展單一結(jié)點的服務(wù)能力來達成相满。如果單結(jié)點服務(wù)能力已經(jīng)擴展到了極限层亿,再尋求擴展的話,就得從軟件到硬件整體進行重構(gòu)立美。
軟件行業(yè)有句話:“Threads don't scale匿又,Processes do!”建蹄,很明確地道出了原來 Monolith 服務(wù)與微服務(wù)在擴展(Scale)層面的差異碌更。
對于Java開發(fā)者來說,早些年(當(dāng)然現(xiàn)在也依然存在)洞慎,我們遵循 Java EE 規(guī)范開發(fā)的 Web 應(yīng)用痛单,都需要以 WAR 包的形式部署到 TOMCAT、Jetty劲腿、RESIN 等 Web 容器中運行旭绒,即使每個 WAR 包提供的都是獨立的微服務(wù),但因為它們都是統(tǒng)一部署運行在一個 Web 容器中焦人,所以擴展能力受限于 Web 容器作為一個進程(process)的現(xiàn)狀挥吵。
無論如何調(diào)整 Web 容器內(nèi)部實現(xiàn)的線程(thread)設(shè)置,還是會受限于 Web 容器整體的擴展能力花椭。所以忽匈,現(xiàn)在很多情況下,大家都是一個 TOMCAT 只部署一個 WAR矿辽,然后通過復(fù)制和擴展多個 TOMCAT 實例來擴展整個應(yīng)用服務(wù)集群泛鸟。
當(dāng)然,說到在 TOMCAT 實例中只部署一個 WAR 包這樣的做法米母,實際上不單單只是因為擴展的因素撩穿,還涉及微服務(wù)運行期間給我們帶來的第二個好處,即隔離性鹊奖。
隔離性實際上是可擴展性的基礎(chǔ),當(dāng)我們將每個微服務(wù)都隔離為獨立的運行單元之后,任何一個或者多個微服務(wù)的失敗都將只影響自己或者少量其他微服務(wù)液走,而不會大面積地波及整個服務(wù)運行體系。
在架構(gòu)設(shè)計上有一種實踐模式贾陷,即隔板模式(Bulkhead Pattern)缘眶,這種架構(gòu)設(shè)計模式的首要目的就是為了隔離系統(tǒng)中的各個功能單元和實體,使得系統(tǒng)不會因為一個單元或者服務(wù)的失敗而導(dǎo)致整體失敗髓废。
這種思路在造船行業(yè)巷懈、兵工行業(yè)都有類似的應(yīng)用場景。現(xiàn)在任何大型船舶在設(shè)計上都會有隔艙慌洪,目的就是即使有少量進水顶燕,也可以只將進水部位隔離在小范圍,不會擴散而導(dǎo)致船舶大面積進水冈爹,從而沉沒涌攻。當(dāng)年泰坦尼克號雖然沉了,但不意味著他們沒有做隔艙設(shè)計频伤,只能說恳谎,傷害度已經(jīng)遠遠超出隔艙可以提供的基礎(chǔ)保障范圍。
在坦克的設(shè)計上憋肖,現(xiàn)在一般也會將彈藥艙和乘員艙隔離因痛,從而可以保障當(dāng)坦克受創(chuàng)之后,將傷害盡量限定在指定區(qū)域岸更,盡量減少對車乘成員的傷害鸵膏。
前面我們提到,現(xiàn)在大家基本上弱化了 Java EE 的 Web 容器早期采用的“一個 Web 容器部署多個 WAR 包”的做法坐慰,轉(zhuǎn)而使用“一個 Web 容器只部署一個 WAR 包”的做法较性,這實際上正是綜合考慮了 Web 容器的設(shè)計和實現(xiàn)現(xiàn)狀與真實需求之后做出的合理實踐選擇。
這些 Web 容器內(nèi)部大多通過類加載器(Classloader)以及線程來實現(xiàn)一定程度上的依賴和功能隔離结胀,但這些機制從基因上決定了這些做法不是最好的隔離手段赞咙。而進程(Process)擁有天然的隔離特性,所以糟港,一個 WAR 包只部署運行在一個 Web 容器進程中才是最好的隔離方式攀操。
現(xiàn)在回想一下,好像自從各個微服務(wù)打響?yīng)毩?zhàn)爭并且獨立之后秸抚,無論從哪個層面來看速和,各自“活”得都挺好歹垫。
多語言生態(tài)
微服務(wù)獨立之后,給了對應(yīng)的團隊和組織快速迭代和交付的能力颠放,同時排惨,也給團隊和組織帶來了更多的靈活性,實際上碰凶,對應(yīng)交付不同微服務(wù)的團隊或者組織來說暮芭,現(xiàn)在可以基于不同的計算機語言生態(tài)構(gòu)建這些微服務(wù),如圖 1 所示欲低。
微服務(wù)的提供者既可以使用 Java 或者 Go 等靜態(tài)語言完成微服務(wù)的開發(fā)和交付辕宏,也可以使用Python或者 Ruby 等動態(tài)語言完成微服務(wù)的開發(fā)和交付,對于團隊內(nèi)部擁有繁榮且有差異的語言文化來說砾莱,多語言生態(tài)下的微服務(wù)開發(fā)和交付將可以最大化的發(fā)揮團隊和組織內(nèi)部各成員的優(yōu)勢瑞筐。
當(dāng)然,對于多語言生態(tài)下的微服務(wù)研發(fā)來說腊瑟,有一點需要注意:為了讓服務(wù)的訪問者可以用統(tǒng)一的接口訪問所有這些用不同語言開發(fā)和交互的微服務(wù)聚假,應(yīng)該盡量統(tǒng)一微服務(wù)的服務(wù)接口和協(xié)議。
在微服務(wù)的生態(tài)下闰非,互通性應(yīng)該是需要重點關(guān)注的因素魔策,沒有互通,不但服務(wù)的訪問者和用戶無法很好地使用這些微服務(wù)河胎,微服務(wù)和微服務(wù)之間也無法相互信賴和互助,這將大大損耗微服務(wù)研發(fā)體系帶來的諸多好處虎敦,而多語言生態(tài)也會變成一種障礙和負累游岳,而不是益處。
記得時任黑貓宅急便社長的小倉昌男在其所著的《黑貓宅急便的經(jīng)營學(xué)》中提到一個故事其徙,日本國鐵曾經(jīng)采用不同于國際標(biāo)準(zhǔn)的集裝箱和鐵路規(guī)格胚迫,然后發(fā)現(xiàn)貨物的運輸效率很低,經(jīng)過考察發(fā)現(xiàn)唾那,原來是貨物從國際標(biāo)準(zhǔn)集裝箱卸載之后访锻,在通過日本國鐵運輸之前,需要先拆箱闹获,重新裝入日本國鐵規(guī)格的集裝箱期犬,然后裝載到日本國鐵上進行運輸。
但是避诽,如果日本國鐵采用國際標(biāo)準(zhǔn)的集裝箱規(guī)格龟虎,那么貨物集裝箱從遠洋輪船上卸載之后就可以直接裝上國鐵,這將大大加快運輸效率(日本沙庐,國鐵改革后也證明確實如此)鲤妥。日本國鐵在前期采用私有方案時佳吞,只關(guān)注了自己的利益和效率,舍棄了互通棉安,也帶來了效率的低下底扳。
所以,在開發(fā)和交付微服務(wù)的時候贡耽,尤其是在多語言生態(tài)下開發(fā)和交付微服務(wù)衷模,我們從一開始就要將互通性作為首要考慮因素,從而不會因為執(zhí)迷于某些服務(wù)或者系統(tǒng)的單點效率而失去了整個微服務(wù)體系的整體效率菇爪。
圖 1??多語言的微服務(wù)生態(tài)