SpringCloud核心組件總結

在這裏插入圖片描述
前幾篇寫了spring cloud的幾個核心組件的原理和一些代碼實現,這篇通篇總結一下。

首先將了微服務和微服務架構的區別,然後明確了微服務架構中面臨的主要挑戰,緊接着引出了基於spring cloud的分佈式微服務開發框架,及其中的核心組件及作用,包括eureka註冊中心、ribbon&feign客戶端服務負載均衡與面向接口調用工具、hystrix服務熔斷與降級、zuul通用api網關服務者四大組件,下面就從頭到尾串聯一下這些內容。

微服務指的是任何一個體積足夠小、功能足夠簡單的服務,它可以是java開發的,也可以是go、node、python開發的,而微服務架構則是一種架構模式,它首先通過服務拆分將整個業務功能拆分層一個個獨立的微服務,然後通過一些通用的服務和組件將他們組裝在一起形成一個整體對外提供服務,微服務架構的核心我個人理解不是服務,而是服務治理,例如服務註冊於發現、調用鏈跟蹤、服務的熔斷與降級等等。

spring cloud是目前java領域最流行的微服務開發框架之一,它基於spring boot構建,spring boot作爲構建微服務的支撐,同時提供了一系列的組件用來完成微服務架構下的服務治理工作。

服務治理的最核心功能應該是服務註冊於發現,spring cloud通過eureka來實現這個功能,spring cloud eureka是spring對netflix eureka的封裝,相對於dubbo zookeeper註冊中心來說,eureka遵循cap定理的ap,即保證了可用性,但在一致性方面做了妥協,從eureka集羣架構上我們也可以看出來,eureka集羣中並沒有類似於master的東西,而是各個節點之間通過複製數據的方式來儘量的保證數據的一致性,所以也就造成了在任意時刻,不同的eureka server中的數據會有微小的差異,因此,在進行服務消費的時候需要做好服務降級的處理工作,因爲有可能會訪問到一個不可用的服務。

整個的eureka架構分爲客戶端和服務端,服務端主要負責對服務列表的維護,提供相應的http接口,同時會定時檢測每個服務的心跳續約,默認沒60秒檢查一次,如果一個服務的心跳續約在90秒內沒有刷新的話,這個服務就會被eureka server踢出服務列表,對於客戶端來說,其實就可簡單理解成是一個個服務了,從eureka的角度老說eureka client並沒有provider和consumer的區別,客戶端主要做兩件事,第一是在服務啓動的時候向eureka server註冊服務信息,第二是以心跳的方式向eureka server發送心跳續約請求,保證服務註冊信息的有效性,這個心跳續約的執行頻率默認是30秒一次,另外eureka還有一個非常有趣的功能就是自我保護機制,在默認情況下,在15分鐘內,如果有效的心跳續約請求不足85%的話,eureka 就會進入到自我保護機制,此時服務列表就會被冷凍,不能進行任何服務信息的刪除操作,這主要是爲了解決分佈式環境下的網絡抖動帶來的消息丟失的問題,這種情況下並不是服務真的不能用,知識由於網絡的原因,客戶端的心跳續約請求有部分丟失,如果直接將服務踢出服務列表的話是不合適的。

由於spring cloud是基於http協議進行調用的,按照正常來說,需要提供ip和端口號,但是這不符合微服務治理的要求,因爲這中調用方式已經脫離了註冊中心,ribbon就是爲了解決這個問題的,ribbon的最主要的功能就是面向服務名稱的調用,即將ip和端口替換成服務名稱,同時,它還提供了負載均衡功能,簡單理解,ribbon就是與註冊中心eureka關聯,當基於服務名稱進行調用時,首先從eureka獲取所有的服務提供者地址,然後按照指定的負載均衡算法找到一個具體的provider再進行http調用,但此時還是通過RestTemplate進行調用,使用起來很不方便,索引就出現了feign,feign是對ribbon的進一步封裝,使得對基於RestTemplate的調用被轉換成了對java接口的調用,同時feign還提供了注入超時時間設置、數據壓縮等功能,進一步對ribbon進行了升級。

hystrix的主要功能是提供服務熔斷和降級的功能,同時它也有一定的服務限流的功能。在微服務架構下,一個客戶端請求通常對應了後端的多個服務,而且調用鏈往往比較深,服務與服務之間的調用也錯綜複雜,一但有一個服務不可用或響應緩慢就會導致服務報錯或請求堆積,造成服務的雪崩,爲了解決這個問題,spring cloud引入了hystrix,基於hystrix的的處理流程是這樣的,首先會判斷hystrix的熔斷器是否開啓,如果開啓,則直接返回給用戶降級結果(降級方式包括fallback method和fallback factory兩種),如果熔斷器未開啓,則判斷線程池和信號量是否已經達到處理上限,如果是則返回降級結果,否則進行服務調用,如果調用過程中出現錯誤或超時,此時會將metrics上報錯誤信息,metrics會統計一個窗口期內的錯誤佔比,來控制斷路器是否開啓。

下面逐一總結一下hystrix的兩種隔離策略和斷路器的觸發條件。hystrix提供了線程池隔離和信號量隔離兩種隔離策略,基於線程池的隔離策略是通過線程池將用戶請求線程和服務調用線程分離,用戶線程通過Future的方式來持有服務調用線程,這種隔離策略的效率比較高,同時支持異步調用和超時控制,基於信號量的隔離級別本質上就是一個計數器,可以簡單理解爲Semaphore,可以通知併發數,但用戶線程和服務調用沒有分離,一個線程懟到底,不支持異步,多數情況下都會使用基於線程池的隔離策略,另外由於線程池和信號量都是有限資源,所以也有一定的限流的作用。

對於熔斷器的觸發規則是基於滑動窗口的,默認一個滑動窗口是10秒,一個滑動窗口被分成10個bucket,metrics會統計每個bucket內部的錯誤數,當錯誤佔比達到指定閾值並且滑動窗口內的請求數量已達到最低限制時,就會開啓熔斷器。例如規定在一個滑動窗口內最少有20個請求,並且失敗佔比超過50%才觸發熔斷器開啓。

當熔斷器開啓後,默認在60秒內會嘗試自動回覆,即重新檢測相關指標是否滿足條件。

zuul是spring cloud中的通用api網關服務,同爲微服務開發框架的dubbo中並沒有提供一個通用的api網關服務,一般我們如果使用dubbo構建微服務架構的時候回自己通過spring mvc這類的web層框架搭建api網關層。zuul作爲api網關的主要作用是提供服務的路由,同時也提供了filter、負載均衡等功能,zuul的本質是Servlet + Ribbon,通過重寫servlet的service方法嵌入filter的邏輯,並通過ribbon實現基於服務名稱的調用,可以說實現原理還是比較簡單的,另外zuul作爲處理請求的最前端,我們也會利用它的filter實現例如限流和權限認證的邏輯。

下面簡單描述一個各個組件的核心實現原理,eureka的實現原理相對比較服務,服務端本質是一個web server,檢測心跳續約的功能通過定時任務完成,客戶端是一個類似於http client的東西與server端進行http通信,心跳續約也是通過定時任務來實現。

ribbon的本質是對RestTemplate進行了一層封裝,內部引入了LoadBalancerInterceptor對調用進行攔截,然後從eureka client的本地緩存中獲取服務列表,並根據具體的負載均衡策略(IRule)從對應的服務列表中選擇一個provider進行調用,從而實現了面向服務的調用和負載均衡的功能。

feign是對ribbon的封裝,它實際上是利用spring的bean掃描和FactoryBean,將對應的接口以BeanDefinition的方式註冊到IoC容器中,並將其與一個指定的FactoryBean關聯,這樣當對接口進行依賴注入的時候,就會調用對應的FactoryBean的getObject方法,而這裏則是通過jdk動態地理的方式將請求轉發到了Ribbon層,同時feign還依賴的hystrix提供了基於整個接口的服務降級策略。

hystrix在實現上大量使用的RxJava反應式編程,由於代碼跟蹤比較困難,小編目前也沒搞的太明白,但在最外層,hystrix是通過spring api對@HystrixCommand註解進行掃描並創建對應的代理對象,來將調用請求接入Hystrix的。

Zuul的原理上面已經說了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章