咱們先認識一下SpringCloud的各個組件,而後知其因此然。算法
原理講解前,先看一個最經典的業務場景,如開發一個電商網站,要實現支付訂單的功能,流程以下:數據庫
如上,微服務的應用場景和核心競爭力:json
Dubbo對標Spring Cloud微服務:緩存
Spring Cloud實現思路:安全
原理:主管服務註冊與發現,也就是微服務的名稱註冊到Eureka,就能夠經過Eureka找到微服務,而不須要修改服務調用的配置文件。服務器
分析:Spring Cloud封裝了Netflix公司開發的Eureka模塊來實現服務的註冊與發現,採用的c-s的設計架構,Eureka Server做爲服務註冊功能的服務器,他是服務註冊中心。而系統的其餘微服務,使用Eureka的客戶端鏈接到Eureka Server並維持心跳。這樣系統的維護人員能夠經過Eureka Server來監控系統中的各個微服務是否正常運行。Spring Cloud的一些其餘模塊(好比Zuul)就能夠經過Eureka Server來發現系統其餘的微服務,並執行相關邏輯。網絡
Eureka Server架構
Eureka Server提供服務註冊服務,各個節點啓動後,會在Eureka Server中進行註冊, 這樣Eureka Server中的服務註冊表中將會存儲全部可用服務節點的信息,服務節點的信息能夠在界面中直觀的看到。併發
Eureka Clientapp
Eureka Client是一個Java客戶端, 用於簡化Eureka Server的交互,客戶端同時也具有一個內置的、 使用輪詢(round-robin)負載算法的負載均衡器。在應用啓動後,將會向Eureka Server發送心跳(默認週期爲30秒),以證實當前服務是可用狀態。若是Eureka Server在必定的時間(默認90秒)未收到客戶端的心跳,Eureka Server將會從服務註冊表中把這個服務節點移除。
Eureka Server的自我保護機制
若是在15分鐘內超過85%的節點都沒有正常的心跳,那麼Eureka就認爲客戶端與註冊中心出現了網絡故障,此時會出現如下幾種狀況:
所以, Eureka能夠很好的應對因網絡故障致使部分節點失去聯繫的狀況,而不會像ZooKeeper那樣使整個註冊服務癱瘓。
Eureka和ZooKeeper
著名的CAP理論指出,一個分佈式系統不可能同時知足C(一致性)、A(可用性)和P(分區容錯性)。因爲分區容錯性在是分佈式系統中必需要保證的,所以咱們只能在A和C之間進行權衡。
ZooKeeper保證CP
當向註冊中心查詢服務列表時,咱們能夠容忍註冊中心返回的是幾分鐘之前的註冊信息,但不能接受服務直接down掉不可用。也就是說,服務註冊功能對可用性的要求要高於一致性。可是ZooKeeper會出現這樣一種狀況,當Master節點由於網絡故障與其餘節點失去聯繫時,剩餘節點會從新進行leader選舉。問題在於,選舉leader的時間太長,30 ~ 120s,且選舉期間整個ZooKeeper集羣都是不可用的,這就致使在選舉期間註冊服務癱瘓。在雲部署的環境下,因網絡問題使得ZooKeeper集羣失去Master節點是較大機率會發生的事,雖然服務可以最終恢復,可是漫長的選舉時間致使的註冊長期不可用是不能容忍的。
Eureka保證AP
Eurek在設計時就優先保證可用性。Eureka各個節點都是平等的,幾個節點掛掉不會影響正常節點的工做,剩餘的節點依然能夠提供註冊和查詢服務。而Eureka的客戶端在向某個Eureka註冊或時若是發現鏈接失敗,則會自動切換至其它節點,只要有一臺Eureka還在,就能保證註冊服務可用(保證可用性),只不過查到的信息可能不是最新的(不保證強一致性)。
除此以外,Eureka還有一種自我保護機制,見上。
總結
Eureka能夠很好的應對因網絡故障致使部分節點失去聯繫的狀況,而不會像ZooKeeper那樣使整個註冊服務癱瘓。
Eureka做爲單純的服務註冊中心來講要比ZooKeeper更加「專業」,由於註冊服務更重要的是可用性,咱們能夠接受短時間內達不到一致性的情況。
在微服務架構中,業務都會被拆分紅一個獨立的服務,服務與服務的通信是基於HTTP RESTful的。Spring Cloud有兩種服務調用方式,一種是Ribbon+RestTemplate,另外一種是Feign。
概念
基於Netflix Ribbon用過輪詢策略實現的一套客戶端負載均衡的工具。
客戶端負載均衡:負載均衡Zuul網關將一個請求發送給某一個服務的應用的時候,若是一個服務啓動了多個實例,就會經過Ribbon來經過必定的負載均衡策略來發送給某一一個服務實例。Spring Cloud中的Ribbon,客戶端會有一個服務器地址列表,在發送請求前經過負載均衡算法(如簡單輪詢,隨機鏈接等)選擇一個服務器,而後進行訪問。
負載均衡
RestTemplate
傳統狀況下在Java代碼裏訪問RESTful服務,通常使用Apache的HttpClient,不過此種方法使用起來太過繁瑣。Spring提供了一種簡單便捷的模板類來進行操做,這就是RestTemplate。
Feign是一個聲明式http客戶端。使用Feign能讓編寫http客戶端更加簡單,它的使用方法是定義一個接口,而後在上面添加註解,避免了調用目標微服務時,須要不斷的解析/封裝json數據的繁瑣。Spring Cloud中Feign默認集成了Ribbon,並和Eureka結合,默認實現了負載均衡的效果。
Ribbon和Feign的區別
Feign目標**使**編寫Java Http客戶端變得更容易
在使用Ribbon+ RestTemplate時,Ribbon須要本身構建http請求,模擬http請求而後使用RestTemplate發送給其餘服務,步驟至關繁瑣。利用RestTemplate對http請求的封裝處理,造成了-套模版化的調用方法。可是在實際開發中,因爲對服務依賴的調用可能不止一處,每每一個接口會被多處調用,因此一般都會針對每一個微服務自行封裝一些客戶端類來包裝這些依賴服務的調用。因此,Feign在此基礎上作了進一步封裝,由他來幫助咱們定義和實現依賴服務接口的定義。
在Feign的實現下,咱們只需建立一個接口並使用註解的方式來配置它(之前是Dao接口上面標註Mapper註解,如今是一個微服務接口上面標註一個Feign註解便可), 便可完成對服務提供方的接口綁定,簡化了使用Spring Cloud Ribbon時,自動封裝服務調用客戶端的開發量。
Feign集成了Ribbon
Ribbon經過輪詢實現了客戶端的負載均衡,而與Ribbon不一樣的是,Feign是一個聲明式的Web服務客戶端, 使得編寫Web服務客戶端變得很是容易,只須要建立一個接口, 而後在上面添加註解,像調用本地方法同樣調用它就能夠,而感受不到是調用遠程方法。SpringCloud中Feign默認集成了Ribbon,並和Eureka結合,默認實現了負載均衡的效果。
Ribbon和Nginx的區別
服務器端負載均衡Nginx
Nginx是客戶端全部請求統一交給Nginx,由Nginx進行實現負載均衡請求轉發,屬於服務器端負載均衡。既請求由Nginx服務器端進行轉發。客戶端負載均衡Ribbon,Ribbon是從Eureka註冊中心服務器端上獲取服務註冊信息列表,緩存到本地,而後在本地實現輪詢負載均衡策略。既在客戶端實現負載均衡。
應用場景的區別
Nginx適合於服務器端實現負載均衡,好比:Tomcat,Ribbon適合與在微服務中RPC遠程調用實現本地服務負載均衡,好比:Dubbo、Spring Cloud中都是採用本地負載均衡。
應用場景
假如當前有十幾個微服務服務,訂單,商品,用戶等等,顯然是客戶端不須要和每一個服務逐一打交道,這就須要有一個統一入口,它就是服務網關。API網關全部的客戶端請求經過這個網關訪問後臺的服務。他可使用必定的路由配置來判斷某一個URL由哪一個服務來處理。並從Eureka獲取註冊的服務來轉發請求。
核心功能
Zuul包含了對請求的路由和過濾兩個最主要的功能,是各類服務的統一入口,同時還會用來提供監控、受權、安全、調度等等。
路由功能:負責將外部請求轉發到具體的微服務實例上,是實現外部訪問統一入口的基礎。
過濾器功能:則負責對請求的處理過程進行干預,是實現請求校驗、服務聚合等功能的基礎。
Zuul和Eureka進行整合:將Zuul自身註冊爲Eureka服務治理下的應用,同時從Eureka中得到其餘微服務的消息,也即之後的訪問微服務都是經過Zuul跳轉後得到。
注意:Zuul服務最終仍是會註冊進Eureka,提供代理+路由+過濾三大功能。
核心原理
Zuul的核心是一系列的filters,其做用能夠類比Servlet框架的Filter,或者AOP。
過濾器之間沒有直接進行通訊,而是經過Request Context(上下文)進行數據傳遞。
Zuul的過濾器是由Groovy寫成,這些過濾器文件被放在Zuul Server上的特定目錄下面,Zuul會按期輪詢這些目錄,修改過的過濾器會動態的加載到Zuul Server中以便過濾請求使用。
Zuul負載均衡:Zuul攔截對應的API前綴請求作轉發,轉發到對應的serverId上,在Eureka服務上同一個serverId能夠對應多個服務,也就是說用同一個服務節點不一樣的端口註冊兩個實例,可是serverId是同樣Zuul作轉發的時候會結合eureka-server起到負載均衡的效果。
過濾器的種類:
Zuul和Nginx
Zuul雖然在性能上和Nginx無法比,但它也有它的優勢。Zuul提供了認證鑑權,動態路由,監控,彈性,安全,負載均衡等邊緣服務,在團隊規模不大的狀況下,沒有專門負責路由開發時,使用Zuul當網關是一個快速上手的好方案。
Nginx和Zuul是能夠配合使用的,發揮各自的優勢,使用Nginx做爲負載均衡實現高併發的請求轉發,Zuul用做網關。
Zuul和Ribbon實現負載均衡
Zuul支持Ribbon和Hystrix,也可以實現客戶端的負載均衡。咱們的Feign不也是實現客戶端的負載均衡和Hystrix的嗎?既然Zuul已經可以實現了,那咱們的Feign還有必要嗎?
能夠這樣理解:
Zuul是對外暴露的惟一接口至關於路由的是controller的請求,而Ribbonhe和Fegin路由了service的請求。
Zuul作最外層請求的負載均衡,而Ribbon和Fegin作的是系統內部各個微服務的service的調用的負載均衡。
介紹
Hystrix是一個用於處理分佈式系統的延遲和容錯的開源庫,在分佈式系統裏,許多依賴不可避兔的會調用失敗,好比超時、異常等,Hystrix可以保證在一個依賴出問題的狀況下,不會致使總體服務失敗,避免級聯故障,以提升分佈式系統的彈性。Hystrix的出現就是爲了解決雪崩效應。
服務雪崩
多個微服務之間調用的時候,假設微服務A調用微服務B和微服務C,微服務B和微服務C又調用其它的微服務,這就是所謂的「扇出」。若是扇出的鏈路上某個微服務的調用響應時間過長或者不可用,對微服務A的調用就會佔用愈來愈多的系統資源,進而引發系統崩潰,所謂的」雪崩效應」。
服務熔斷
熔斷機制是應對雪崩效應的一種微服務鏈路保護機制。
當刪除鏈路的某個微服務不可用或者響應時間太長時,會進行服務的降級,進而熔斷該節點微服務的調用,快速返回」錯誤的響應信息。當檢測到該節點微服務調用響應正常後恢復調用鏈路。在SpringCloud框架裏熔斷機制經過Hystrix實現。Hystrix會監控微服務間調用的情況,當失敗的調用到必定閾值,缺省是5秒內20次調用失敗就會啓動熔斷機制。熔斷機制的註解是@HystrixCommand。
服務降級
總體資源快不夠了,忍痛將某些服務先關掉,待渡過難關,再開啓回來。
Hystrix監控和斷路器
咱們只須要在服務接口上添加Hystrix標籤,就能夠實現對這個接口的監控和斷路器功能。
Hystrix Dashboard監控面板,提供了一個界面,能夠監控各個服務上的服務調用所消耗的時間等。
Hystrix Turbine監控聚合
使用Hystrix監控,咱們須要打開每個服務實例的監控信息來查看。而Turbine能夠幫助咱們把全部的服務實例的監控信息聚合到一個地方統查看。這樣就不須要挨個打開一個個的頁面一個個查看。
Zuul的安全機制
簽名機制,爲防止接口數據篡改和重複調用,增長接口參數校驗機制,sig簽名算法爲MD5(appKey+appSecret+timestamp),appKey是分配給客戶端的ID,appSecret是分配給客戶端的密鑰,timestamp爲unix時間戳,請求的URL有效時間爲15分鐘。
Token機制,用戶在登陸以後會返回一個access_ token,客戶端在訪問須要登陸以後才能訪問的資源,須要在在Authorization頭部使用Bearer模式新增token,如head(「Authorization」,」 Bearer token」)。
Hystrix的設計原則
介紹
Spring Cloud Config是一個解決分佈式系統的配置管理方案。微服務意味着要將單體應用中的業務拆分紅一個個子服務,每一個服務的粒度相對較小,所以系統 中會出現大量的服務。因爲每一個服務都須要必要的配置信息才能運行,因此一套集中式的、 動態的配置管理設施是必不可少的。Spring Cloud提供了ConfigServer來解決這個問題,咱們每個微服務自 己帶着一個application.yml 上百個配置文件的管理。
應用場景
原理
角色
歡迎你們關注個人公衆號【風平浪靜如碼】,海量Java相關文章,學習資料都會在裏面更新,整理的資料也會放在裏面。
以爲寫的還不錯的就點個贊,加個關注唄!點關注,不迷路,持續更新!!!