Spring Cloud全家桶開箱即用,中小型公司用得比較多,包含了很多組件(網關,配置中心,熔斷,降級。。)。本文介紹最核心的Eureka、Ribbon、Feign、Hystrix、Zuul這幾個組件。
1.Eureka
Eureka中每台機器都是peer-to-peer的,集群中的機器地位平等,各個服務可以向任何一個Eureka實例注冊和發現。集群中的任何一個Eureka接收到寫請求后,會自動同步給所有的Eureka實例。與Dubbo使用的一致性同步機制CP不同,Eureka使用的是AP。使用默認的配置服務上下線服務感知的時效性是非常糟糕的,可能需要幾十秒,甚至是分鍾級別的。
服務注冊中心原理入下圖所示:
其中 服務A,服務B,服務C都有Eureka Client組件,這些組件負責將服務的注冊信息注冊到 Eureka服務中。
Eureka是一個注冊中心,里面保存了一個注冊表,用於記錄各個服務所在的機器信息,端口號。
2.Feign
訂單服務注冊中心確實知道服務A、服務B、服務C在哪里了,同時也監聽着哪些端口號了。
但是當他們要之間需要進行通信的時候,難道要手動寫一大堆代碼,讓他們建立網絡連接,封裝他們需要傳遞的參數,發送請求,並對相應的數據進行處理?
如果你是基於SpringCloud對外發布一個接口,實際上是基於http協議的,對外發布的就是一個最最普通的SpringMVC接口。
Feign,通過對一個接口打上注解,他會基於這個注解標注的接口生成動態代理,然后針對Feign的動態代理去調用他的方法時,會在底層生成http協議格式的請求,
IP:端口號/order/create?productId=1
最后針對這個地址,發起請求、解析響應。
3.Ribbon
如果A服務部署在兩台機器上面,Feign如何知道請求哪台機器呢? Ribbon就派上用場了
Feign底層使用的是HttpClient,先得使用Ribbon從本地的Eureka注冊表的緩存里獲取出對方的機器列表
然后再進行Ribbon根據 負載均衡算法 選擇一台機器出來
Feign就會針對這台機器發送Http請求
4.Hystrix
Hystrix是一個隔離,熔斷,降級的框架。
隔離:當服務A請求調用服務B,C時,請求服務B時一個線程池,請求服務C是一個線程池。相互之間互不影響
熔斷:當服務A完成一項邏輯業務,需要調用服務B, 如果服務B掛掉了,每次調用到會被卡住幾秒鍾,會影響用戶的操作體驗,我們一般直接對服務B熔斷,不走網絡請求的那幾秒鍾,這個過程,就是熔斷。
降級:服務B熔斷了,此時服務B不能啥都不干啊,此時,就來個降級,此時需要往數據庫表或日志文件中記錄一條消息,說某個用戶因為服務B掛掉,進行的操作沒成功,並且帶上參數,等到 服務B服務再次回復,你可以根據這些記錄手動補上記錄。
5.Zuul
這個組件主要負責 網絡路由, 當你部署的Spring Cloud集群達到了幾百個的時候,每個服務實例都有自己的名字,當你需要調用的時候,不可能基於每個服務實例的名字,一個個去調用,此時就需要一個集中的網關。
有了網關,如果前端、移動端要調用后端系統,不用管后台有多少服務實例,所有的請求只需直接走網關,網關會將請求轉發給后台的所有微服務。
注冊發現時間調整
eureka server:
eureka: server: #關閉自我保護 enable-self-preservation: false #ReadWrite緩存同步到ReadOnly緩存,注冊表信息 response-cache-update-interval-ms: 2000 #專門的線程定期檢查注冊表信息的間隔時間 eviction-interval-timer-in-ms: 4000 instance: hostname: server #超過5秒無心跳將client干掉 lease-expiration-duration-in-seconds: 5 #服務掛掉,發送心跳的時間 lease-renewal-interval-in-seconds: 2 client: #服務實例,每隔2秒拉取一下注冊表信息 registry-fetch-interval-seconds: 2 fetch-registry: true register-with-eureka: true serviceUrl: defaultZone: http://localhost:8081/eureka
eureka client:
# 注冊中心 eureka: client: # 服務發現每隔2秒拉取一下注冊表信息 registry-fetch-interval-seconds: 2 serviceUrl: defaultZone: http://localhost:8081/eureka/ instance: instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${server.port} #超過5秒無心跳將client干掉 lease-expiration-duration-in-seconds: 5 #服務掛掉,發送心跳的時間 lease-renewal-interval-in-seconds: 2
總結:
Eureka: 服務啟動時,Eureka Client都會將服務注冊到Eureka Server
同時Eureka Client還可以反過來從Eureka Server拉取注冊表,從而知道其他服務在哪里
Ribbon: 服務間發起請求時,基於Ribbon做負載均衡,從一個服務的多台機器中選擇一台
Feign: 基於動態代理機制,根據注解,拼接請求URL地址,選擇機器,發起請求
Hystrix: 服務間的請求走不同的Hystrix線程池,避免了服務雪崩
Zuul: 提供統一的請求入口,Zuul會將這些請求轉發給相對應的服務