本節書摘來自華章出版社《springboot揭秘:快速建構微服務體系》一書中的第1章,第1.3節微服務會帶來哪些好處,作者王福強,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。
1.3 微服務會帶來哪些好處
顯然,随着系統複雜度的提升,以及對系統擴充性的要求越來越高,微服務化是一個很好的方向,但除此之外,微服務還會給我們帶來哪些好處?
1.3.1 獨立,獨立,還是獨立
我們說微服務打響的是各自的獨立戰争,是以,每一個微服務都是一個小王國,這些微服務跳出了“大一統”(monolith)王國的統治,開始從各個層面打造自己的獨立能力,進而保障自己的小王國可以持續穩固的運轉。
首先,在開發層面,每個微服務基本上都是各自獨立的項目(project),而對應各自獨立項目的研發團隊基本上也是獨立對應,這樣的結構保證了微服務的并行研發,并且各自快速疊代,不會因為所有研發都投入一個近乎單點的項目,進而造成開發階段的瓶頸。開發階段的獨立,保證了微服務的研發可以高效進行。
服務開發期間的形态,跟服務傳遞期間的形态原則上是不需要完全高度統一的,即使我們在開發的時候都是各自進行,但傳遞的時候還是可以一起傳遞,不過這不是微服務的做法。在微服務治理體系下,各個微服務傳遞期間也是各自獨立傳遞的,進而使得每個微服務從開發到傳遞整條鍊路上都是獨立進行,這大大加快了微服務的疊代和傳遞效率。
服務傳遞之後需要部署運作,對微服務來說,它們運作期間也是各自獨立的。
微服務獨立運作可以帶來兩個比較明顯的好處,第一個就是可擴充性。我們可以快速地添加服務叢集的執行個體,提升整個微服務叢集的服務能力,而在傳統monolith模式下,為了能夠提升服務能力,很多時候必須強化和擴充單一結點的服務能力來達成。如果單結點服務能力已經擴充到了極限,再尋求擴充的話,就得從軟體到硬體整體進行重構。
軟體行業有句話:“threads don't scale, processes do!”,很明确道地出了原來monolith服務與微服務在擴充(scale)層面的差異。
對于java開發者來說,早些年(當然現在也依然存在),我們遵循java ee規範開發的web應用,都需要以war包的形式部署到tomcat、jetty、resin等web容器中運作,即使每個war包提供的都是獨立的微服務,但因為它們都是統一部署運作在一個web容器中,是以擴充能力受限于web容器作為一個程序(process)的現狀。無論如何調整web容器内部實作的線程(thread)設定,還是會受限于web容器整體的擴充能力。是以,現在很多情況下,大家都是一個tomcat隻部署一個war,然後通過複制和擴充多個tomcat執行個體來擴充整個應用服務叢集。
當然,說到在tomcat執行個體中隻部署一個war包這樣的做法,實際上不單單隻是因為擴充的因素,還涉及微服務運作期間給我們帶來的第二個好處,即隔離性。
隔離性實際上是可擴充性的基礎,當我們将每個微服務都隔離為獨立的運作單元之後,任何一個或者多個微服務的失敗都将隻影響自己或者少量其他微服務,而不會大面積地波及整個服務運作體系。在架構設計上有一種實踐模式,即隔闆模式(bulkhead pattern),這種架構設計模式的首要目的就是為了隔離系統中的各個功能單元和實體,使得系統不會因為一個單元或者服務的失敗而導緻整體失敗。這種思路在造船行業、兵工行業都有類似的應用場景。現在任何大型船舶在設計上都會有隔艙,目的就是即使有少量進水,也可以隻将進水部位隔離在小範圍,不會擴散而導緻船舶大面積進水,進而沉沒。當年泰坦尼克号雖然沉了,但不意味着他們沒有做隔艙設計,隻能說,傷害度已經遠遠超出隔艙可以提供的基礎保障範圍。在坦克的設計上,現在一般也會将彈藥艙和乘員艙隔離,進而可以保障當坦克受創之後,将傷害盡量限定在指定區域,盡量減少對車乘成員的傷害。
前面我們提到,現在大家基本上弱化了java ee的web容器早期采用的“一個web容器部署多個war包”的做法,轉而使用“一個web容器隻部署一個war包”的做法,這實際上正是綜合考慮了web容器的設計和實作現狀與真實需求之後做出的合理實踐選擇。這些web容器内部大多通過類加載器(classloader)以及線程來實作一定程度上的依賴和功能隔離,但這些機制從基因上決定了這些做法不是最好的隔離手段。而程序(process)擁有天然的隔離特性,是以,一個war包隻部署運作在一個web容器程序中才是最好的隔離方式。
現在回想一下,好像自從各個微服務打響獨立戰争并且獨立之後,無論從哪個層面來看,各自“活”得都挺好。
1.3.2 多語言生态
微服務獨立之後,給了對應的團隊群組織快速疊代和傳遞的能力,同時,也給團隊群組織帶來了更多的靈活性,實際上,對應傳遞不同微服務的團隊或者組織來說,現在可以基于不同的計算機語言生态建構這些微服務,如圖1-2所示。
微服務的提供者既可以使用java或者go等靜态語言完成微服務的開發和傳遞,也可以使用python或者ruby等動态語言完成微服務的開發和傳遞,對于團隊内部擁有繁榮且有差異的語言文化來說,多語言生态下的微服務開發和傳遞将可以最大化的發揮團隊群組織内部各成員的優勢。當然,對于多語言生态下的微服務研發來說,有一點需要注意:為了讓服務的通路者可以用統一的接口通路所有這些用不同語言開發和互動的微服務,應該盡量統一微服務的服務接口和協定。
在微服務的生态下,互通性應該是需要重點關注的因素,沒有互通,不但服務的通路者和使用者無法很好地使用這些微服務,微服務和微服務之間也無法互相信賴和互助,這将大大損耗微服務研發體系帶來的諸多好處,而多語言生态也會變成一種障礙和負累,而不是益處。
記得時任黑貓宅急便社長的小倉昌男在其所著的《黑貓宅急便的經營學》中提到一個故事,日本國鐵曾經采用不同于國際标準的集裝箱和鐵路規格,然後發現貨物的運輸效率很低,經過考察發現,原來是貨物從國際标準集裝箱解除安裝之後,在通過日本國鐵運輸之前,需要先拆箱,重新裝入日本國鐵規格的集裝箱,然後裝載到日本國鐵上進行運輸。但是,如果日本國鐵采用國際标準的集裝箱規格,那麼貨物集裝箱從遠洋輪船上解除安裝之後就可以直接裝上國鐵,這将大大加快運輸效率(日本,國鐵改革後也證明确實如此)。日本國鐵在前期采用私有方案時,隻關注了自己的利益和效率,舍棄了互通,也帶來了效率的低下。是以,在開發和傳遞微服務的時候,尤其是在多語言生态下開發和傳遞微服務,我們從一開始就要将互通性作為首要考慮因素,進而不會因為執迷于某些服務或者系統的單點效率而失去了整個微服務體系的整體效率。
