單體應用 VS 微服務
讓我們先從運維的真實場景出發,來看一下單體應用存在的問題。這里先分享兩個真實的生產案例:
案例一是某核心業務系統,所有的業務邏輯代碼都打包在同一個WAR包里部署,運行了將近幾百個同構的實例在虛擬機上。某次因為應用包中的一個功能模塊出現異常,導致實例掛起,整個應用都不能用了。因為它是一個單體,所以盡管有幾百個實例在運行,但是這幾百個實例都是異常的。業務系統是經過多年建設起來的,排查起來也很復雜,最終整個業務系統癱瘓了近六個小時才恢復。同時,因為有多個前臺系統也調用了這個后臺系統,導致所有要調用的前臺系統也都全部癱瘓了。設想一下,如果這個場景使用的是微服務架構,每個微服務都是獨立部署的,那影響的也只是有異常的微服務和其他相關聯的服務,而不會導致整個業務系統都不能使用。
另外的案例是一個客服系統,這個系統有一個特點,早上八點的時候會有大量的客服登錄。這個登錄點是全天中業務并發量最高的時間點,登錄時系統需要讀取一些客戶信息,加載到內存。后來一到早上客服登錄時,系統經常出現內存溢出,進而導致整個客服系統都用不了。當時系統應對這種場景做架構冗余時,并不是根據單獨的業務按需進行擴展,而是按照單體應用的長板進行冗余。比如說早上八點并發量最高,單點登陸模塊業務需求非常大,為適應這個時間點這個模塊的業務壓力,系統會由原來的八個實例擴展到十六個實例,這時的擴展是基于整個系統的。但事實上,在其他時間段,這個單點登陸模塊基本不使用,且監控的數據顯示,主機的資源使用情況基本在40%以下,造成了很大的資源浪費。所以在一個大型的業務系統中,每個服務的并發壓力不一樣,如果都按壓力最大的模塊進行整體擴展,就會造成資源的浪費,而在微服務的模式下,每個服務都是按自身壓力進行擴展的,就可以有效的提高資源利用率。
從這兩個例子中,我們可以看出,單體應用存在如下兩個問題:一個是橫向擴展時需要整體擴展,資源分配最大化,不能按需擴展和分配資源;另一個是如果單體中有一個業務模塊出現問題,就會是全局性災難,因為所有業務跑在同一個實例中,發生異常時不具備故障隔離性,會影響整個業務系統,整個入口都會存在問題。
因此,我們當時考慮把綜合業務拆分,進行更好的資源分配和故障隔離。

下面我們看一下單體應用和微服務的對比,如表所示。這里從微服務帶來的好處和額外的復雜性來講。
微服務的好處:
1.局部修改,局部更新。當運維對一個單體應用進行修改時,可能要先把整個包給停了,然后再去修改,而微服務只需逐步修改和更新即可;
2.故障隔離,非全局。單體應用是跑在一起,所以只要一個模塊有問題,其他就都會有問題。而微服務的故障隔離性、業務可持續性都非常高;
資源利用率高。單體應用的資源利用率低,而使用微服務,可以按需分配資源,資源利用率會非常高。
微服務帶來的復雜性:
1.微服務間較強的依賴關系管理。以前單體應用是跑在一起,無依賴關系管理,如果拆成微服務依賴關系該如何處理,比如說某個微服務更新了會不會對整個系統造成影響。
2.部署復雜。單體應用是集中式的,就一個單體跑在一起,部署和管理的時候非常簡單,而微服務是一個網狀分布的,有很多服務需要維護和管理,對它進行部署和維護的時候則比較復雜。
3.如何更好地利用資源。單體應用在資源分配時是整體分配,擴展時也是整體擴展,數量可控,而在使用微服務的情況下,需要為每一個微服務按需分配資源,那么該為每個微服務分配多少資源,啟動多少個實例呢,這也是非常大的問題。
4.監控管理難。以前我們用Java,就是一個單體應用,監控和管理非常簡單,因為它就是一個1,但是使用微服務它就是N個,監控管理變得非常復雜。另外是微服務之間還有一個協作的問題。
基于容器構建微服務架構
使用微服務,第一步是要構建一個一體化的DevOps平臺,如圖。如果你不使用DevOps做微服務的話,整個環境會變得非常的亂、非常的糟糕。它會給你的整個開發、測試和運維增加很多成本,所以第一步我們是提高DevOps的能力,能夠把它的開發、部署和維護進行很完美的結合,才可以說我們真正能夠享受到微服務架構的福利。

容器的出現給微服務提供了一個完美的環境,因為我們可以:
1.基于容器做標準化構建和持續集成、持續交付等。
2.基于標準工具對部署在微服務里面的容器做服務發現和管理。
3.透過容器的編排工具對容器進行自動化的伸縮管理、自動化的運維管理。
所以說,容器的出現和微服務的發展是非常相關的,它們共同發展,形成了一個非常好的生態圈。下面詳細講下DevOps的各個模塊。
持續集成與持續發布
持續集成的關鍵是完全的自動化,讀取源代碼、編譯、連接、測試,整個創建過程自動完成。我們來看一下如何用Docker、Maven、Jenkins完成持續集成。

如圖所示。首先是開發人員把程序代碼更新后上傳到Git,然后其他的事情都將由Jenkins自動完成。那Jenkins這邊發生什么了呢?Git在接收到用戶更新的代碼后,會把消息和任務傳遞給Jenkins,然后Jenkins會自動構建一個任務,下載Maven相關的軟件包。下載完成后,就開始利用Maven Build新的項目包,然后重建Maven容器,構建新的Image并Push到Docker私有庫中。然后刪除正在運行的Docker容器,再基于新的鏡像重新把Docker容器拉起來,自動完成集成測試。整個過程都是自動的,這樣就簡化了原本復雜的集成工作,一天可以集成一次,甚至是多次。
依賴關系管理
前面講到,當微服務多的時候,依賴關系管理也會比較復雜,現在比較流行的是基于消費者驅動的契約管理。在開發一個微服務時,并不需要另外一個微服務開發完后再做集成測試,而是使用契約的方式。契約通過提供標準化的輸出,說明請求的內容、回復的內容、交換的數據,開發微服務時符合契約里這些條件即可。

如圖所示,微服務A通過模擬與微服務B的交互,將交互內容保存在契約里,而微服務B開發時需滿足這個契約里的條件,這樣就不需要A和B完全完成了才能做測試。當很多微服務與微服務B關聯時,每個微服務通過契約告訴微服務B請求的內容、正確的響應和請示的數據,然后微服務B通過契約模擬這個測試過程,而其他的微服務則需要滿足這個契約。當微服務進行升級時,也是要先滿足所有契約,這樣微服務間的關系就可以更好的進行管理。
典型的微服務架構
典型的微服務架構模型,采用的是Kubernetes框架。把業務系統拆分成很多的微服務,然后通過服務注冊的方式去發現整個生產環境中所有的微服務,通過負載均衡組件進行分發,再用服務調度去進行彈性伸縮,而客戶端則只需要通過API網關訪問微服務。除此之外,微服務的運維也很重要。開發是實現功能性需求,而在實際的生產環境中,我們更應該關心非功能性的需求。因為即使功能實現了,跑到生產上卻不能用,功能開發再完美也沒有用。

服務發現與負載均衡
服務發現與負載均衡使用的是Kubernetes的架構,如圖。每一個微服務都有一個IP和PORT,當調用一個微服務時,只需要知道微服務的IP,而不需要關心容器的IP,也不需要關心pod的IP。雖然每個pod也有IP和PORT,但當一個pod啟動時,就會把pod的IP和PORT注冊到服務發現模塊,再進行負載均衡。所以當多個pod啟動時,對于用戶來說還是只需要知道service的IP,不需要知道后端啟動了多少pod、IP是多少,這就解決了網絡的問題。

日志集中式管理

以前單體的情況下,單體的數量少,日志數量也相應比較少,而在微服務架構下,因為拆分成了很多微服務,相應的日志會非常多且散,這種情況下需要對日志進行集中的管理。我們可以在每個容器里跑日志監控,把所有日志采集進行集中管理和存儲,再通過簡易操作的UI界面進行索引和查詢。
監控管理

然后就是監控方面了。微服務的量是非常大的,這個時候如何有效地監控是極其重要的。我們剛開始做監控的時候,有幾百個實例對同一個關鍵字進行監控,出故障后會收到幾百條短信,因為每一個實例都會發一條短信。這時候嚴重的致命性的報警就會看不到,因為手機信息已經爆炸了,所以要對報警進行分級,精確告警,最重要的是盡量讓故障在發生之前滅亡。因此,在做監控時要對故障提前進行判斷,先自動化處理,再看是否需要人為處理,然后通過人為的干預,有效的把故障在發生之前進行滅亡。
但如果所有事情都靠人為去處理,這個量也是非常大的,所以對故障進行自動化隔離和自動化處理也很重要。我們在寫自動化故障處理的時候研究了很多常見的故障,寫了很多算法去判斷,精確到所有的故障,這樣基本的常見的故障和可以策劃處理的故障都可以自動化處理掉。之前沒有出現的故障,出現之后我們就會去研究是否可以做成自動化處理。如果生產上做的不精確,對生產會是災難性的,所以我們對生產的故障自動化處理也做了很多研究。
七牛的微服務架構實踐
前面講了很多運維,下面來了解一下Docker和微服務在七牛云中的實踐,以七牛的文件處理服務架構演變為例。
文件處理服務是指,用戶把原圖存到七牛的云存儲之后,然后使用文件處理服務,就可以把它變成自己想要的服務,比如剪裁、縮放和旋轉等,如圖。

過去為適應不同的場景,用戶需要針對同一圖片自行處理后上傳所有版本,但如果使用七牛的文件處理服務,則只需提供原圖就可以了,其他版本的圖片都可以通過七牛進行處理。如圖所示,我們把一張原圖放進去之后,只需要在原圖后面加一個問號和參數,就可以呈現出想要的方式,比如說加水印、旋轉、縮放和剪裁。

文件處理服務的架構在早期是非常笨拙的,如圖所示。FopGate是業務的入口,通過work config靜態配置實際進行計算的各種worker集群的信息,里面包含了圖片處理、視頻處理、文檔處理等各種處理實例。集群信息在入口配置中寫死了,后端配置變更會很不靈活,因為是靜態配置,突發請求情況下,應對可能不及時,且FopGate成為流量穿透的組件(業務的指令流與數據流混雜在一起),比如說要讀一張圖片,這張圖片會經過FopGate導過來。

于是,我們自己組建了一個叫Discovery的服務,由它進行負載均衡和服務發現,用于集群中worker信息的自動發現,每個worker被添加進集群都會主動注冊自己,FopGate從Discovery獲取集群信息,完成對請求的負載均衡。同時在每個計算節點上新增Agent組件,用于向Discovery組件上報心跳和節點信息,并緩存處理后的結果數據(將數據流從入口分離),另外也負責節點內的請求負載均衡(實例可能會有多個)。此時業務入口只需負責分發指令流,但仍然需要對請求做節點級別的負載均衡。這是第二個階段,如圖。

在第三個階段,我們把文件處理架構遷移到了容器平臺上,取消了業務的Discovery服務,轉由平臺自身的服務發現功能。每個Agent無需和Discovery維護心跳,也不再需要上報節點信息,每個Agent對應一個計算worker,并按工種獨立成Service,比如ImageService、VideoService,由于后端只有一個worker,因此也不需要有節點內的負載均衡邏輯,業務入口無需負載均衡,只需請求容器平臺提供的入口地址即可,如圖所示。

上一個階段中,每個Agent仍然和計算實例綁定在一起,而這么做其實只是為了方便業務的無痛遷移,因為Agent本身的代碼會有一些邏輯上的假設。在第四階段中,如圖,我們進一步分離了Agent和worker,Agent獨立成一個Service,所有的worker按工種獨立成Service。這么分離的目的在于,Agent可能會有文件內容緩存,屬于有狀態的服務,而所有的worker是真正干活、無狀態的服務。分離之后的好處在于,worker的數量可以隨時調整和伸縮,而不影響Agent中攜帶的狀態。可以看到,相比于最早的架構,業務方只需集中精力開發業務本身,而無需重復造輪子,實現各種復雜的服務發現和各種負載均衡的代碼。另外,自從部署到容器平臺之后,平臺的調度器會自動根據節點的資源消耗狀況做實例的遷移,這樣使得計算集群中每個節點的資源消耗更加均衡。

踩過的那些坑

圖所示的是單體應用訪問后端數據庫使用的數據庫連接池,連接池里的連接是可以復用的,而單體中所有的業務模塊都可以調用同一個池里的連接。這個數據庫連接池可以進行動態的伸縮,但它連接到后端數據庫的連接是有上限的。拆分成微服務之后,可能每一個微服務都要創建一個數據庫連接池,微服務間的數據庫連接池并不能共享。當對微服務進行彈性伸縮時,并不知道它會彈性到什么程度,這時就可能會對后端數據庫造成連接風暴,比如原本只有五千個長連接,但是由于彈性伸縮(可能根據前臺業務情況進行了非常大的伸縮),會對數據庫發生連接風暴,對數據庫造成非常大的壓力。
為了確保不會因某個服務的連接風暴把數據庫拖垮,對其他服務造成影響,我們做了一些優化。首先是優化了我們的一些彈性算法,其次是限定了容器彈性伸縮的范圍,因為沒有限制的伸縮,可能會對后端數據庫造成壓力。另外一個是降低連接池初始化的大小,比如初始化設定為10,它往數據庫里面的長連接就是100個,如果設定為1,往數據庫里面長連接就只有10個,如果太多則可能會對數據庫造成壓力。還有就是數據庫端進行一些限定,當連接達到一定數量就進行預警,限制彈性擴展。
我在傳統企業工作了七八年,我們一直在探討單體應用如何拆分成微服務。其實對傳統企業來講,他們的單體是非常大的,而且內部的耦合性是非常強的,內部調用非常多。如果我們冒冒失失地將單體拆分成微服務,會占用非常大的網絡傳輸。如果在拆成微服務的時候,沒有進行很好的架構設計,拆成微服務并不是享受它帶來的好處,而是災難。所以在拆的時候,比如說前端、后端的拆分、耦合性不是特別強的拆分,我們提倡先跑到容器里面,看一下運維容器的時候有什么坑,然后解決這些坑,然后不斷完善。我們可以把耦合性不是那么高的拆成大的塊,然后把信息密集型的進行拆分,慢慢拆分成我們理想的架構。這是一個循序漸進的過程,不可一蹴而就。

以上是微服務的一些設計準則,例如設計提倡最小化功能,小到不能再小。這時需要每一個服務標準化的提供出來,有一個標準化的接口和其他微服務進行通信。還需要是異步通信,如果是同步會造成堵塞。每個微服務都要有獨立的數據存儲。此外,服務還需要是無狀態的,因為如果有狀態,彈性伸縮時可能會有數據丟失,可以用一些其他的方法處理這些有狀態的數據。
核心關注:拓步ERP系統平臺是覆蓋了眾多的業務領域、行業應用,蘊涵了豐富的ERP管理思想,集成了ERP軟件業務管理理念,功能涉及供應鏈、成本、制造、CRM、HR等眾多業務領域的管理,全面涵蓋了企業關注ERP管理系統的核心領域,是眾多中小企業信息化建設首選的ERP管理軟件信賴品牌。
轉載請注明出處:拓步ERP資訊網http://www.guhuozai8.cn/
本文標題:從運維的角度看微服務和容器
本文網址:http://www.guhuozai8.cn/html/support/11121820033.html