服務治理和負載均衡
微服務架構廣泛應用在超高並發系統中,中后台服務集群的規模着實不小。就拿淘系的下單接口來說,一個下單指令要調用近二十個后台微服務協同完成任務(可能現在更多了),而在雙11這類業務場景下,核心鏈路的一個微服務背后的虛機數量都有近萬台。
因此,服務與服務之間的調用,就成了微服務架構需要解決的第一個問題。與此同時,大規模集群中虛機的上線下線是每天的日常任務,集群的擴容縮容也很常見,我們的微服務架構需要探知到集群中各個服務節點的狀態變化,這樣就知道哪些節點是可以正常提供服務的。我們管這個領域叫做服務治理
與服務治理搭檔的還有負載均衡,面對茫茫多的服務器,如何將海量用戶請求分發到不同的機器。考慮到有的機器性能比較弱,或者機房帶寬不大,網絡響應慢,如何根據實際情況動態地分發服務請求?這個領域就是負載均衡需要解決的事情。
熔斷降級
若你依賴的服務長時間響應失敗或者超時錯誤次數頻增,你是否就要考慮估計你的下游服務生病了,或者處理算力不夠了,我們就要像參考電路板熔斷器一樣,我就不去調用你了,這種機制我們把它叫做“熔斷”,基於熔斷保護下游,給下游一個喘息的機會,一旦熔斷之后我們還要間歇性的去觀察下游是否恢復了,因為熔斷非常態,正常服務才是我們的訴求,我們還需要提供說我間歇性的訪問下你,比如每個2秒鍾訪問你一次,如果連續三次都沒有異常,則判斷你已經恢復了,我關閉熔斷處理策略。在熔斷的過程中我們需要定義一種異常,這種異常比如我們可以用一個特殊的錯誤碼,一種特殊的異常,或者就是一個null的返回,我們對應的服務消費要基於這個錯誤碼做到可降級,比如我們的商品銷量獲取,如果服務不可用我們就可以展示一個默認的銷量,或者隱藏掉銷量的展示,不要把系統錯誤拋給前端。hystrix框架提供給我們和好的服務隔離和熔斷機制,結合dubbo的插件式編程方式做很好的融合
服務通信
隔離開系統之后,本來進程內的調用就要改成進程之間的調用了,進程之間的調用最常用的方式就是網絡通信,而遠程的網絡通信調用函數的方式就是RPC(Remote Process Call)遠程過程調用,其並非是一個簡單的網絡通信過程,在java中依靠接口代理的通信機制使用服務消費方在進程內可以像調用本地函數一樣去調用服務提供方的代碼,其中間層由dubbo的服務代理機制負責搞定。
對,RPC通信框架使得服務調用就這么簡單
服務注冊及發現,解決了服務通信的網絡問題,大家不要忽略了,我的服務消費方怎么知道提供方的ip地址和端口,然后連接上去做服務通信的,dubbo結合zookeeper的注冊和發現的通信能力做到了這一點
服務提供方啟動后將自己的ip,端口及可以提供的demoService的接口簽名注冊到zookper的注冊中心上
服務消費方啟動后通過自己的reference服務依賴引用列表從注冊中心找到了提供demoService接口簽名的接口服務提供方,也就是我們的服務提供方的ip和端口
當consumer要調用對應的demoService服務時通過本地存儲的提供方ip和端口連接到provider並進行服務調用后獲得返回
當provider產生問題,例如異常退出后,由於和zookeeper注冊中心之間的心跳丟失,注冊中心判定provider死亡會主動通知關注demoService的服務消費方consumer,consumer於是就將對應的provider ip和端口及連接提出
發送方和接收方定義將服務調用量發送給monitor監控器做服務健康監控負載均衡
在上圖服務注冊和發現中其實我們的provider和consumer在分布式環境下是多台的,因此我們的consumer可以通過注冊中心拿到一批provider的ip和端口,當發生服務調用時可以在本地存儲的provider列表上做負載均衡策略,比如可以輪訓或隨機的取下一次調用的provider的連接,由於上述第4步的存在,若某台provider故障則consumer會立馬通過注冊中心感知到並將provider踢出對應的列表,當provider恢復后又會到注冊中心注冊,consumer又可以得到通過將provider加回。
服務容錯
地盤大了難免雜事不斷,集群中難免有那么幾台機器跑着跑着就慷慨就義了。那么對於其它的服務調用者來說,如果不巧正好調用到了這些掛掉的機器,那自然會獲得到失敗的Response。面對這種情況,后台服務可有另一條路走?
在高並發場景下,有的服務會承擔較大的訪問請求,這有可能導致響應時間過慢,甚至會響應超時。那調用方在超時后經常會發起重試,這樣會進一步增加下游應用的訪問壓力,進而導致一個惡性循環。那么面對這種情況,我們有解決方案嗎?
以上就是微服務領域中降級和熔斷技術需要解決的問題,我們管這些叫做服務容錯。
配置管理
大家平時在項目中都怎么管理配置項呢?使用配置文件?如果我有一個業務場景,需要隨時調整配置,這種配置文件的管理方式可能就玩不轉了,我們總不能每次改配置的時候都要重啟機器吧。
那么把配置項存到數據庫里?可以倒是可以,但是訪問量增加的時候也會將壓力傳導到數據庫,數據庫往往是比較弱不禁風的一環,很可能被壓垮。那么放到緩存里?這一定程度上解決了性能問題,不過在某些業務場景下還是不好用,比如我希望給不同服務器配置不同屬性值,指定name屬性在某100台機器中的值是張三,在剩余機器中的值是李四。
以上問題在微服務領域也不是什么大問題,服務配置管理就是專門解決這類問題的利器。
服務網關
我們的系統對外提供的網絡訪問入口只有一個,這通常就是一個域名網址。但是這套系統后面的服務器可有千千萬,那么在微服務架構下,是如何將用戶請求轉發到每個不同的服務器上的呢?這就是服務網關需要解決的事情。
前面我們學習過Nginx網關,大家也應該了解了網關的含義,不過在微服務領域里,網關層會更加智能一些,它會感知服務器上下線的變化。欲知微服務網關如何與服務治理搭配使用,且聽下回分解。
網關接入系統負責接收對應的web請求,轉發給對應后面的業務服務系統處理對應的業務並接收返回轉發給前端。后面的業務服務系統各司其職,每個系統只負責自己業務范圍內的職責,比如商品系統僅服務商品相關的服務,創建,更新,查詢,上下架等整個的生命周期並被購物車系統依賴,服務系統之間的邏輯關系清晰,且不同系統間只能通過對方提供的接口做訪問,管理方便,每個系統擁有自己獨立部署服務器,擁有自己的存儲數據庫,故障可隔離,配合日志,消息,監控,配置中心等分部署微服務下的配合組件做到一個可監控,可隔離,又可通信的服務體系。
調用鏈路追蹤
前面提到一個淘系下單場景會調用一連串的微服務,我們YY這么一個線上故障,有個用戶買了兩只大豬蹄子,結果東西送到家變成了兩只雞爪子。店小二說沒發錯貨啊不信自己看訂單,打開一看還真是,下單的時候選的豬蹄子,下單以后就成了雞爪子。
上面這個問題出在整個下單鏈路哪個環節呢?是訂單中心搞錯了商品ID,還是購物車頁面傳了錯誤ID給訂單系統,或者說搜索頁面一鍵下單功能沒取到正確的ID?迷霧迷霧在迷霧,怎么撥開迷霧見真相?
調用鏈追蹤,從前到后整個調用鏈路全景數據展現,用事實說話,從此甩鍋更加精准!
消息驅動
消息驅動是老朋友了,相信大家在項目中也經常使用消息中間件。我們試想這樣一個場景,雙11當天24點0分0秒一過,數萬萬的敗家親們一擁而上,下單接口調用量飆升,就快到了崩潰邊緣。那我們后台的訂單服務如何才能頂住這一波波攻勢?親,消息驅動組件加上限流組件來做削峰填谷了解一下?
不僅如此,微服務各個系統之間的解耦也可以用消息組件來實現。其實消息驅動在微服務里的實現也就是多做了幾層抽象,調用起來更加方便,個中滋味還請同學們親身體驗。
限流
再厲害的系統也有性能瓶頸,強如阿里打造的雙十一也抵不住全國剁手族齊上陣,限流是最經濟高效,在源頭處消減系統壓力的手段。微服務的后台服務節點數量龐大,單機版限流遠不能解決問題,我們需要在服務器集群這個范圍內引入分布式限流手段。
監控
我們需要一套監控體系配合我們的微服務健康度檢查,在出現問題的時候可以快速定位問題,甚至於做到提前發現問題,防患於未然,dubbo自身的monitor並不能提供給我們太好的支持,在這里我建議大家看一下點評開源的cat監控組件,結合dubbo的插件式編程方式,將每一個服務調用以打點的方式打到cat上,並提供給我們一種可視化的監控展現。