微服務化之無狀態化與容器化

2022-06-06 14:45:09 字數 3819 閱讀 8252

此文已由作者劉超授權網易雲社群發布。

一、為什麼要做無狀態化和容器化

很多應用拆分成微服務,是為了承載高併發,往往乙個程序扛不住這麼大的量,因而需要拆分成多組程序,每組程序承載特定的工作,根據併發的壓力用多個副本公共承擔流量。

將乙個程序變成多組程序,每組程序多個副本,需要程式的修改支撐這種分布式的架構,如果架構不支援,僅僅在資源層建立多個副本是解決不了問題的。

很多人說,支撐雙十一是靠堆機器,誰不會?真正經歷過的會覺得,能夠靠堆機器堆出來的,都不是問題,怕的是機器堆上去了,因為架構的問題,併發量仍然上不去。

阻礙單體架構變為分布式架構的關鍵點就在於狀態的處理。如果狀態全部儲存在本地,無論是本地的記憶體,還是本地的硬碟,都會給架構的橫向擴充套件帶來瓶頸。

狀態分為分發,處理,儲存幾個過程,如果對於乙個使用者的所有的資訊都儲存在乙個程序中,則從分發階段,就必須將這個使用者分發到這個程序,否則無法對這個使用者進行處理,然而當乙個程序壓力很大的時候,根本無法擴容,新啟動的程序根本無法處理那些儲存在原來程序的使用者的資料,不能分擔壓力。

所以要講整個架構分成兩個部分,無狀態部分和有狀態部分,而業務邏輯的部分往往作為無狀態的部分,而將狀態儲存在有狀態的中介軟體中,如快取,資料庫,物件儲存,大資料平台,訊息佇列等。

這樣無狀態的部分可以很容易的橫向擴充套件,在使用者分發的時候,可以很容易分發到新的程序進行處理,而狀態儲存到後端。而後端的中介軟體是有狀態的,這些中介軟體設計之初,就考慮了擴容的時候,狀態的遷移,複製,同步等機制,不用業務層關心。

如圖所示,將架構分為兩層,無狀態和有狀態。

容器和微服務是雙胞胎,因為微服務會將單體應用拆分成很多小的應用,因而運維和持續整合會工作量變大,而容器技術能很好的解決這個問題。然而在微服務化之前,建議先進行容器化,在容器化之前,建議先無狀態化,當整個流程容器化了,以後的微服務拆分才會水到渠成。

二、無狀態化的幾個要點

前面說對於任何狀態,需要考慮它的分發,處理,儲存。

對於資料的儲存,主要包含幾類資料:

如果這些資料都儲存在本地,和業務邏輯耦合在一起,就需要在資料分發的時候,將同乙個使用者分到同乙個程序,這樣就會影響架構的橫向擴充套件。

對於儲存在記憶體裡的資料,例如session,可以放在外部統一的快取中。

對於業務相關的資料,則應該儲存在統一的資料庫中,如果效能扛不住,可以進行讀寫分離,如文章微服務化的資料庫設計與讀寫分離

如果效能還是抗住不,則可以使用分布式資料庫。

對於檔案,**之類的資料,應該存放在統一的物件儲存裡面,通過cdn進行預載入,如文章微服務的接入層設計與動靜資源隔離

對於非結構化資料,可以存在在統一的搜尋引擎裡面,例如elasticsearch。

如果所有的資料都放在外部的統一儲存上,則應用就成了僅僅包含業務邏輯的無狀態應用,可以進行平滑的橫向擴充套件。

而所有的外部統一儲存,無論是快取,資料庫,物件儲存,搜尋引擎,都有自身的分布式橫向擴充套件機制。

在實行了無狀態化之後,就可以將有狀態的集群集中到一起,進行跨機房的部署,實現跨機房的高可用性。而無狀態的部分可以通過dubbo自動發現,當程序掛掉的時候,自動重啟,自動修復,也可以進行多機房的部署。

三、冪等的介面設計

但是還有乙個遺留的問題,就是已經分發,正在處理,但是尚未儲存的資料,肯定會在記憶體中有一些,在程序重啟的時候,資料還是會丟一些的,那這部分資料怎麼辦呢?

這部分就需要通過重試進行解決,當本次呼叫過程中失敗之後,前序的程序會進行重試,例如dubbo就有重試機制。既然重試,就需要介面是冪等的,也即同一次交易,呼叫兩次轉賬1元,不能最終轉走2元。

介面分為查詢,插入,更新,刪除等操作。

對於查詢介面來講,本身就是冪等的,不用做特殊的判斷。

對於插入介面來講,如果每乙個資料都有唯一的主鍵,也能保證插入的唯一性,一旦不唯一,則會報錯。

對於更新操作來講,則比較複雜,分幾種情況。

一種情況是同乙個介面,前後呼叫多次的冪等性。另一種情況是同乙個介面,併發環境下呼叫多次的正確性。

為了保持冪等性,往往要有乙個冪等表,通過傳入冪等引數匹配冪等表中id的方式,保證每個操作只被執行一次,而且在實行最終一致性的時候,可以通過不斷重試,保證最終介面呼叫的成功。

對於併發條件下,誰先呼叫,誰後呼叫,需要通過分布式鎖如redis,zookeeper等來實現同乙個時刻只有乙個請求被執行,如何保證多次執行結果仍然一致呢?則往往需要通過狀態機,每個狀態只流轉一次。還有就是樂觀鎖,也即分布式的cas操作,將狀態的判斷、更新整合在一條語句中,可以保證狀態流轉的原子性。樂觀鎖並不保證更新一定成功,需要有對應的機制來應對更新失敗。

四、容器的技術原理

無狀態化之後,實行容器化就十分順暢了,容器的不可改變基礎設施,以及容器基於容器平台的掛掉自動重啟,自動修復,都因為無狀態順暢無比。

關鍵技術一:dockerfile

例如下面的dockerfile。

為什麼一定要用dockerfile,而不建議通過儲存映象的方式來生成映象呢?

這樣才能實現環境配置和環境部署**化 ,將dockerfile維護在git裡面,有版本控制,並且通過自動化的build的過程來生成映象,而映象中就是環境的配置和環境的部署,要修改環境應先通過git上面修改dockerfile的方式進行,這就是iac。

關鍵技術二:容器映象

通過dockerfile可以生成容器映象,容器的映象是分層儲存,對於dockerfile中的每乙個語句,生成一層容器映象,如此疊加,每一層都有uuid。

容器映象可以打乙個版本號,放入統一的映象倉庫。

關鍵技術三:容器執行時

容器執行時,是將容器映象之上加一層可寫入層,為容器執行時所看到的檔案系統。

容器執行時使用了兩種隔離的技術。

一種是看起來是隔離的技術,稱為namespace,也即每個namespace中的應用看到的是不同的ip位址、使用者空間、程號等。

另一種是用起來是隔離的技術,稱為cgroup,也即明明整台機器有很多的cpu、記憶體,而乙個應用只能用其中的一部分。

cgroup

網易雲計算基礎服務深度整合了 iaas、paas 及容器技術,提供彈性計算、devops 工具鏈及微服務基礎設施等服務,幫助企業解決 it、架構及運維等問題,使企業更聚焦於業務,是新一代的雲計算平台,點選可免費試用。

高手之路 服務無狀態化設計與實踐

登入成功 使用者的session存放在哪一層?閘道器層使用者的sesson怎麼存放 外部儲存 統一的分布式儲存 客戶端儲存,每次請求攜帶資料 x 記憶體中。即使是id通過hash,固定到一台,但是還是有可能因為機器掛了,導致出現問題 redis集群擴容方案 由於使用者量的增加,原來乙個128個節點的...

虛擬化與容器化

安裝 1.使用root許可權操作 安裝命令 yum install docker 2.檢查安裝是否成功 檢查命令docker version 若輸出了 docker 的版本號,說明安裝成功了,可通過以下命令啟動 docker 服務 3.docker啟動命令service docker start 一...

什麼是DevOps? 虛擬化 容器 微服務

提到devops這個詞,我相信很多人一定不會陌生。作為乙個熱門的概念,devops近年來頻頻出現在各大技術社群和 的文章中,備受行業大咖的追捧,也吸引了很多吃瓜群眾的圍觀。那麼,devops是什麼呢?有人說它是一種方法,也有人說它是一種工具,還有人說它是一種思想。更有甚者,說它是一種哲學。越說越玄乎...