微服務架構下,如何打造別具一格的服務治理體驗?(下)
作者介紹
張真,宜信技術研發中心高級架構師,負責基礎係統架構演進與優化、服務治理、監控平台、微服務建設、DevOps平台、自動化測試框架及電子簽約、短信、郵件等應用係統。早年就職於IBM中國研發中心,負責IBM WebSphere應用服務器的設計與開發。目前主要關注微服務架構實施,微智能設計思想應用,虛擬化技術應用,共識計算研究。
上文我們已經詳細講到了一些經典微服務架構的特點及問題,微服務計算平台的設計思想與抽象模型,今天就接著打造微服務計算的基礎三件事這一話題,說說服務情景感知與監控和服務調用的自適應機製。
一、服務情景感知與監控
高效的服務運維需要實現對服務的有效監控。微服務計算平台在設計上考慮了兩個方麵:
-
服務運行的監控
-
服務上下文的監控
1服務運行的監控
服務運行的監控是針對服務處理能力的監控,常規的指標包括吞吐量(QPS),響應時間,錯誤,響應碼等等。
我們采用了自動發現+自動捕獲的方式:
-
服務能力實現框架中Http服務框架除了可以被畫像以外,也天然集成了指標計數器。
-
在服務接口運行的過程中,各種指標計數器被更新。
-
基礎服務能力“服務監控捕獲”定期從Http服務框架采集各個服務接口的指標數據並打包成監控數據。
-
服務監控捕獲會將監控數據通過消息隊列發送到具備服務能力“服務監控存儲”的計算節點。
當然實際上基於JAVA的微服務計算節點,還會采集很多JVM的指標,它們包括Heap各個區的使用狀態,GC次數&累計時間,Class加載情況,進程CPU占用率,線程使用狀況等。
監控數據采用JSON作為傳輸格式
2服務上下文的監控
服務上下文是服務計算節點運行環境,主要是係統層麵的監控:CPU占用率,內存使用狀況,連接數量,相關端口的進出流量(KB),磁盤使用狀況等等。服務上下文的狀況會直接影響服務運行的性能以及健壯性。
微服務計算中的情節感知
首先,每個服務計算節點通過服務能力“運行環境感知”調用各種係統功能來獲取監控數據。這些係統功能一般包括三類:
-
係統命令:操作係統內置的命令,常用的有netstat,top,du,df。通過netstat可以獲得當前進程所有監聽端口以及連接數;通過top可以獲得當前進程的CPU占用率和內存消耗。通過df命令可以獲得各個掛載的磁盤消耗,du命令可以獲取節點進程占用的相關目錄的磁盤消耗。
-
係統API:獲取進程各個端口的進出流量,需要通過Raw Socket來截取。使用C或Python編程調用Raw Socket API來實現。
-
係統目錄:Linux係統所有係統行為基本上都有一組文件對應。比如為了實現服務計算節點的自動值守或自重啟,通過readlink讀取/proc/<進程id>/XX下的信息,通過這些信息可以構建任意進程的啟動命令。
通常來說,優先使用係統命令,因為原生,執行代價小;係統API是應對較為底層的監控數據獲取;係統目錄需要深入操作係統了解運行機理,代價最大,但是也最為準確。需要根據實際情況而定。
然後,運行環境感知會將捕獲到的監控數據通過心跳客戶端發送給心跳服務端,再由心跳服務端交由服務能力“運行環境監控存儲”實現持久化。情景感知數據是另一種心跳數據,之所以采用心跳係統來傳輸的原因是:
-
與服務注冊接口數據保持高度的時間同步性,因為微服務計算平台期望每個服務計算節點根據上下文監控數據進行自適應調整,這個話題也會在以後的分享專題中進行說明。
-
上下文監控數據無需“高頻”(間隔30秒~1分鍾)采集且指標數量固定,這意味著實際Payload不大,這符合Http攜帶數據的特性,也能保證其隨多級心跳上行。
那麼為什麼服務監控數據是通過消息隊列傳輸,而不是使用心跳上行?主要是以下原因:
-
監控數據的使用方式不同:服務監控數據指導自動適應調節是依靠一段時間內的指標數據的聚集結果(比如平均值,求和值等),這也可以消除係統誤差,而非依靠“瞬時”數據,而且這個過程需要服務監控數查詢提供運算支持;上下文監控數據是客觀反映服務計算節點的環境狀況,瞬時數據保證精確性,可以直接使用,反而一段時間的聚集結果會丟失精確性。
-
服務監控數據的數據量會遠遠大於上下文監控數據: 服務監控數據量=服務接口數量*指標個數*采集頻率。因為它采用頻率更高(間隔5秒~15秒),服務接口數量會遠遠大於服務計算節點數量,除了固定的一些指標外,可以包含業務指標,隨之指標數量會增加許多。心跳係統不適合“重,多”的場景,而消息隊列適合數據Payload大的場景,且一定程度保證數據有序。此外,消息隊列會持久化數據,防止由於接收端宕機導致的數據丟失。
二、服務調用的自適應機製
服務調用過程中往往會遇到各種異常。單體架構的年代,由於基本都是內存調用,幾乎很少遇到這類問題,隻有在跨係統的時候才會出現;到了SOA的時代,逐漸出現了服務調用問題,不過主要是服務與服務總線(Service Bus)之間,服務連接到服務總線也缺少容錯機製。微服務架構出現以後,服務之間的依賴變得直接而且更多元化,麵對龐大的服務接口如何使其更“平順,聰明,可靠”是一個必須解決的問題。
“服務熔斷”是微服務架構的熱詞之一,這本是個電力工程的術語,原意大致是當輸入鏈路電力過載時,為了保護下遊鏈路以及設備,自動“熔斷”電力鏈路。最常見的就是保險絲機製。
那麼服務熔斷又是什麼含義呢?主要體現以下三個方麵:
-
失效自動切換(Failover)
-
失效隔離(Isolation)
-
自動高效重試(Retry)
如果再加上服務調用的負載均衡(Load Balance),其本質體現的是服務調用的自適應。
服務調用自適應基本模型
自適應機製的體現實際也是服務計算節點/服務接口的資源可用性的狀態轉化過程:
-
可用的計算節點/服務接口是能夠被負載均衡機製發現的;
-
服務調用中出現異常,調用方會切換好的資源,而異常的資源可能被隔離起來;
-
需要通過重試來確定異常的資源是否恢複,是否解除隔離;
-
重試成功的資源會解除隔離,變成可用狀態而被負載均衡機製發現;
-
多次重試都失敗的資源,可能被更”強”的隔離起來。
下麵會分別解讀它們是如何實現的。
1負載均衡與失效自動切換
在微服務計算平台中,負載均衡與失效切換是密不可分的,這裏會放在一起說明。
負載均衡分為兩種模式:
-
代理模式:通過前置代理,代理向後對接服務計算節點,比如Ngnix,HAProxy。經典NetFlix微服務架構中的“服務網關”實際上也是一個代理,它對外是代理網關,對內則類似服務總線。
-
客戶端模式:由調用客戶端決定使用何種策略來訪問目標服務。像Dubbo,Dubbox等就是使用Zookeeper客戶端獲取服務地址列表,然後使用負載均衡策略來訪問服務。
兩種模式沒有“絕對”的優劣之分,主要看適用場景。在微服務架構下,客戶端模式應該更加適合。
微服務計算平台中的負載均衡是由服務能力實現框架提供的一種通用型組件。無論是何種通信協議(HTTP,RPC,RMI等)實際都可以統一成一種通用型組件。負載均衡的實質是對調用目標的策略,關於負責均衡的策略很多,也有很多實現算法,本節不做討論。
它的處理機製是:
-
每個服務接口注冊以後,都可以通過服務注冊中心的API(對外暴露的服務,人工調用)來設置這些服務接口的負載均衡策略。
-
在服務發現的過程,調用方業務服務能力X除了可以獲得服務接口地址列表,還同時獲得了服務接口的負載均衡策略,此外還有失效切換策略。這麼做也可以實現策略的動態更新。
在負責輪轉的過程中,如果出現調用異常,則需要進行失效切換的操作。服務調用異常可分為四類:
-
服務接口地址無法連接
-
服務調用超時異常: 目標服務計算節點可能進程存活,但由於某種原因無法響應或hang住。這中場景通常棘手,不容易第一時間發現,危害比服務計算節點掛掉更大,會拖延整個調用鏈路恢複的時間
-
業務處理異常(係統性,可恢複):由於目標服務的處理過程以及上下文環境造成的異常,這種異常的特點是換一個同類型的服務計算節點異常可能就解決了。
舉個例子,電子簽章服務在處理文件簽章時,需要一個臨時目錄來做暫存,如果因為某種原因使得該服務所在的機器上磁盤滿了,導致臨時目錄無法寫入,這時簽章調用就會失敗。但如果切換到另外一個磁盤未滿的節點上,調用就成功了。
-
業務處理異常(業務數據引起,難以恢複):目標服務的處理過程是“完好正確”的,但由於業務數據的問題(數據格式,數據內容缺失,數據一致性等等)造成調用失敗。請注意,這類異常通常不能進行切換。
所以失效切換實質是對前三類異常進行切換,我們把切換分為兩類:
-
非通異常切換:針對連接不可用異常和調用超時異常。
-
業務異常切換:針對係統性的業務處理異常。注意,這是客戶端模式獨有的切換方式,因為在代理模式下無法識別業務異常類型,甚至無法識別業務異常(例如業務上在響應報文中提示異常,但HTTP響應碼仍然是200)。
前文在說明服務注冊與發現時提到了服務接口失效的快速反饋,它為失效服務接口地址提交提供了通道,使得其他可能的調用方能夠不再去嚐試失效服務接口地址,也為失效資源隔離提供了全局視圖。
微服務計算平台還提供了一項“黑科技”,是基於動態服務編排的切換機製。這種切換機製可以不依賴與人工設置,它能夠自主的根據目標服務能力需求,全網同類型服務能力計算節點的運行狀況來做出決策,決定由哪個或哪些服務計算節點來完成計算任務。這會在以後的專題分享中進行解讀。
2自動高效重試
重試是服務接口失效後的補償操作,它的目的是為了確認失效資源是否“Back Online”。
微服務計算平台中的重試也是由服務能力實現框架提供的能力,也是通用型組件的一部分。我們把它設計成與負載均衡,失效切換一體化的機製:
-
首先,服務調用重試是由第一個發生對該服務接口進行失效切換的節點來嚐試,這個節點會緩存這個服務接口地址
-
在這個節點進行負載均衡的某次請求中,會再次返回失效的服務接口地址,當然是以保證隻有這次請求的線程獲得,而其他並發請求的線程是按照正常的負載均衡策略進行的。之所以這樣做是因為:
1)無需引入額外資源來進行重試,沒有維護額外資源的代價
2)用盡可能小的代價進行重試,僅僅是某次請求的線程
在業務服務能力類型很多,且關聯複雜時,實際很難實現一個合適的重試機製。因為往往微服務之間的編排不像做一個網絡探測一樣容易
-
如果這次重試成功,調用方節點立即解除隔離,並將這個“好消息”上傳到服務注冊中心服務注冊中心則可以“通知”所有可能的調用方。
-
如果經過多次重試(失效切換策略決定)後仍然不成功,也將這個“壞消息”上傳到服務注冊中心,服務注冊中心會根據隔離策略進行相關的動作。
3失效隔離
失效隔離是有前提的,不一定所有調用失敗的服務接口都能隔離。這個前提是被隔離的服務接口不會對業務或數據一致性產生影響。比如如果某個服務計算節點的某服務能力是作為分片持久化數據的一個節點,如果該節點被隔離可能造成分片錯誤,這時則不能隔離該節點。
失效隔離可以分為:
-
失效軟隔離(調用隔離):在服務的可訪問性上進行隔離。這種隔離是從調用方角度來考慮,而對失效額服務計算節點本身不會施加影響。比如讓某個服務接口地址從服務地址列表中消失。軟隔離應該是隔離場景中最常見的,也使用最多。
-
失效強隔離(資源隔離):在服務使用的資源上進行隔離。這種隔離不僅僅從服務可訪問性上,也會直接對失效的服務接口施加操作。比如如果因為磁盤寫錯誤問題造成某個服務計算節點上的某個服務能力出問題,則直接停止該服務能力,注意隻是停止了一個服務能力,而不是服務計算節點,除非該節點上所有服務能力都不可用,則應停止該節點。
微服務計算平台以失效軟隔離為主,也支持失效強隔離。它的處理機製是:
-
在服務注冊中心收到失效反饋後,將服務注冊緩存中對應的服務接口信息置為不可用,這樣在其他服務計算節點通過心跳下行刷新地址列表時,該服務接口的地址將不可見。當然這中間會因為延遲,出現“二次失效反饋”的現象,但由於每個服務計算節點會使用相同的失效切換策略,從業務上是保障正確的。
-
對於某些多次重試都失敗的服務計算節點,服務注冊中心會采用強隔離。由服務注冊中心直接調用該服務計算節點的管控接口(心跳也會注冊這個接口),提交停止服務能力命令
-
該節點的心跳客戶端收到命令後,調用服務能力生命周期管理API來停止服務能力。當然有時候失效隔離策略也是“挽救”策略。例如某個證書申請服務接口失效了,從經驗上講可能隻要重啟一下就可以解決問題,那麼在設置隔離策略時,將隔離操作的命令改為停止並啟動其對應的服務能力,那麼最終該證書申請服務接口的服務能力是被重啟了,當它被再次重試時,就會從強隔離中解除。
其實服務隔離除了失效隔離,還有一種是防禦隔離,也是“熔斷”的一部分,它不是因為服務失效,恰恰服務運行是正常的,而因為業務上或安全上的某個需求,主動進行隔離的方式,比如某些服務計算節點受到請求轟炸,為了避免業務鏈條癱瘓,將收到轟炸的服務計算節點停服。關於這方麵的內容會與以後分享專題中的軟件定義服務集群(SDSC)一起介紹。
三、總結
本文從經典的微服務治理係統的特點和問題出發,結合“微智能”思想,“擬社會化”分布式設計來考慮微服務計算平台的節點抽象模型。並在該模型基礎上就微服務計算的三項基礎:服務注冊與發現,服務情景感知與監控,服務調用的自適應分別進行說明,如何落地微服務節點抽象模型。
當然微服務計算平台的建設還包括一些話題:
-
外部如何訪問(集成問題),API網關的實現
-
服務之間的信任以及外部訪問授權
-
服務SLA如何量化,如何讓係統聰明的使用
-
動態服務集成與編排
-
動態計算編排
-
原文發布時間為:2016-11-29
本文來自雲棲社區合作夥伴DBAplus
最後更新:2017-05-11 14:01:23