spring cloud五大組件分別為:
-
服務發現--Netflix Eureka
-
客戶端負載均衡--Netflix Ribbon
-
斷路器--Netflix Hystrix
-
服務網關--Netflix Zuul
-
分布式配置--Spring Cloud Config
業務場景介紹:
先來給大家說一個業務場景,假設咱們現在開發一個電商網站,要實現支付訂單的功能,流程如下: -
創建一個訂單之后,如果用戶立刻支付了這個訂單,我們需要將訂單狀態更新為“已支付”
-
扣減相應的商品庫存
-
通知倉儲中心,進行發貨
-
給用戶的這次購物增加相應的積分
針對上述流程,我們需要有訂單服務、庫存服務、倉儲服務、積分服務。整個流程的大體思路如下:
-
用戶針對一個訂單完成支付之后,就會去找訂單服務,更新訂單狀態
-
訂單服務調用庫存服務,完成相應功能
-
訂單服務調用倉儲服務,完成相應功能
-
訂單服務調用積分服務,完成相應功能
至此,整個支付訂單的業務流程結束
-
核心組件Eureke(服務發現):
是微服務架構中的注冊中心,由Eureka Client和Eureka Server兩部分組成,前者負責將各個服務的信息注冊到Eureka Server中。后者為注冊中心,里面有一個注冊表,保存了各個服務所在的機器和端口號; -
核心組件Feign(動態代理):
使用了動態代理的機制,用注解定義一個FeignClient接口,向指定的服務建立連接、發起請求、獲取響應,解析響應等等。
Feign的動態代理機制:
- 首先,對某個接口定義了@FeignClient注解,Feign就會針對這個接口創建一個動態代理
- 接着你要是調用這個接口,本質就會調用Feign創建的動態代理,這是核心中的核心;
- Feign的動態代理會根據你接口上的@RequestMapping等注解,來動態構造出你要請求的服務地址;
- 最后針對這個地址,發起請求,解析響應;
- 核心組件Ribbon(客戶端負載均衡):
- Ribbon的作用是負載均衡,當我們要請求的服務部署在多台機器上時,Feign就不知道該請求哪台機器。此時具有負載均衡作用的Ribbon就會幫你在每次請求時選擇一台機器,均勻的把請求分發到各台機器上。
- Ribbon的負載均衡使用的是最經典的Round Robin輪詢算法。簡單說就是對多台機器進行輪流請求,然循環;
- 此外Ribbon是和Feign以及Eureka緊密協作的,具體如下:
- 首先Ribbon會從Eureka Client里獲取到對應的服務注冊表,知道所有的服務都部署在了哪些機器上,在監聽哪些端口號。
- 然后Ribbon就使用默認的Round Robin輪詢算法,從中選擇一台機器;
- 最后Feign就會針對這台機器,構造並發起請求。
- 核心組件Hystrix(斷路器)
業務背景:
- 假設一個業務場景:訂單服務在一個業務流程里需要調用三個服務。現在假設訂單服務自己最多只有100個線程可以處理請求,然后呢,積分服務不幸的掛了,每次訂單服務調用積分服務的時候,都會卡住幾秒鍾,然后拋出—個超時異常。這也是雪崩問題的雛形所在;
- 在上面的業務場景下,如果系統處於高並發狀態,大量的請求涌過來的時候。訂單服務的100個線程都會卡在請求積分服務這塊兒。導致訂單服務沒有一個線程可以處理請求。然后就會導致別人請求訂單服務的時候,發現訂單服務也掛了,不響應任何請求了————這個,就是微服務架構中恐怖的服務雪崩問題。
這邊插入一個思考:就算積分服務掛了,訂單服務也可以不掛啊?為什么?
(1). 結合業務來看:支付訂單的時候,只要把庫存扣減了,然后通知倉庫發貨就OK了。
(2). 如過積分服務掛了,大不了等他回復之后,慢慢人肉手工恢復數據!為啥一定要因為一個積分服務掛了,就直接導致訂單服務也掛了呢?
分析了這么多,就是為了引出我們的Hystrix
- Hystrix是隔離、熔斷以及降級的一個框架。Hystrix會為每個服務搞一個小小的線程池。
下面來說說,當有Hystrix參與時,積分服務掛了會是啥樣的: - 因為上面說了,Hystrix會為各個服務搞一個線程池,當積分服務掛了時,訂單服務那里用來調用積分服務的線程會都卡死不能工作。但是,訂單服務調用庫存服務和倉儲服務的這兩個線程池都能正常工作,所以這兩個服務不會受到任何影響。
- 熔斷————這個時候如果別人調用訂單服務,訂單服務還可以正常調用庫存服務扣減庫存,調用倉儲服務通知發貨。當調用積分服務時每次都會報錯。但是既然積分服務掛了,每次調用都會卡幾秒,這樣顯然是沒有意義的。這里就要用到所謂的熔斷:比如在五分鍾內請求積分服務直接就返回了,不要走網絡請求卡住幾秒鍾。
- 降級————上面說了,積分服務掛了我們就熔斷然后直接返回,這顯然不是最好的解決方法。這個時候就要用到降級處理:每次調用積分服務時,就在數據庫里記錄一條消息,說給某某用戶增加了多少積分,因為積分服務掛了,導致沒增加成功!這樣等積分服務恢復了,就可以根據這些記錄手工加一下積分。這就是所謂的降級處理。
小結:針對微服務框架的服務雪崩問題,我們會用到Hystrix組件,然后進行隔離、熔斷、降級處理。
- 核心組件Zuul(服務網關)
- Zuul就是微服務網關。這個組件是負責網絡路由。
- 如果不懂網絡路由,那我們來看看,沒有Zuul的工作會是怎么樣的:
假設你后台部署了幾百個服務,現在有個前端兄弟,人家請求是直接從瀏覽器那兒發過來的。比如:人家要請求一下庫存服務,你難道要讓人家記住這個服務的名字叫什么什么?部署在幾台機器上?但是后台可能有幾百個服務的名稱和地址,這顯然不能靠記; - 上面這種情況壓根兒是行不通的。所以一般微服務架構中都必然會設計一個網關在里面,像Android、iOS、PC前端、微信小程序、H5等等,不用去關心后端有幾百個服務,就知道有一個網關,所有的請求都走網關,網關會根據請求中的一些特征,將請求轉發給后端各個服務;而且有了網關之后還可以做統一的降級、限流、認證授權、安全,等等;
總結: - Eureka:各個服務啟動時,Eureka Client都會將服務注冊到Eureka Server,並且Eureka Client還可以反過來從Eureka Server拉去注冊表,從而知道其他服務在哪里;
(在spring cloud中,除了可以使用eureka作為注冊中心外,還可以使用zookeeper、Consul作為注冊中心。) - Ribbon:服務間發起請求的時候,基於Ribbon做負載均衡,從一個服務的多台機器中選擇一台;
- Feign:基於Feign的動態代理機制,根據注解和選擇的機器,拼接請求的URL地址,發起請求;
- Hystrix:發起請求是通過Hystrix的線程池來走的,不同的服務走不同的線程池,實現了不同服務調用的隔離,避免了服務雪崩的問題;
(Sentinel可以很好的替代Hystrix) - Zuul:如果前端、移動端要調用后端系統,統一從Zuul網關進入,由Zuul網關轉發請求給對應的服務;
(Gateway可以很好的替代Zuul)
下面通過一張圖來將Spring Cloud五組件聯系起來,直觀了解其底層的架構原理:
(網絡資源)