SpringCloud系列文章同步網址點選閱讀原文直達,歡迎交流探討。
SpringCloud系列文章同步網址點選閱讀原文直達,歡迎交流探討。
SpringCloud系列文章同步網址點選閱讀原文直達,歡迎交流探討。
本文原始碼+筆記:連結:
本文原始碼+筆記:連結:
Hystrix是一個用於處理分散式系統的延遲和容錯的開源庫,在分散式系統裡,許多依賴不可避免的會呼叫失敗,比如超時、異常等,Hystrix能夠保證在一個依賴出問題的情況下,不會導致整體服務失敗,避免級聯故障,以提高分散式系統的彈性。
“斷路器”本身是一種開關裝置,當某個服務單元發生故障之後,透過斷路器的故障監控(類似熔斷保險絲),向呼叫方返回一個符合預期的、可處理的備選響應(FallBack),而不是長時間的等待或者丟擲呼叫方無法處理的異常,這樣就保證了服務呼叫方的執行緒不會被長時間、不必要地佔用,從而避免了故障在分散式系統中的蔓延,乃至雪崩。
本文原始碼+筆記:連結:
熔斷機制是應對雪崩效應的一種微服務鏈路保護機制。
當扇出鏈路的某個微服務不可用或者響應時間太長時,會進行服務的降級,進而熔斷該節點微服務的呼叫,快速返回”錯誤”的響應資訊。當檢測到該節點微服務呼叫響應正常後恢復呼叫鏈路。
在SpringCloud框架裡熔斷機制透過Hystrix實現。Hystrix會監控微服務間呼叫的狀況,當失敗的呼叫到一定閾值,預設是5秒內20次呼叫失敗就會啟動熔斷機制。熔斷機制的註解是@HystrixCommand。
1。建立新的子工程,來演示服務熔斷,子工程名為microservicecloud-provider-dept-hystrix-8001
2。在microservicecloud-provider-dept-hystrix-8001工程的pom檔案裡新增如下jar包:
xsi:schemaLocation=“http://maven。apache。org/POM/4。0。0 http://maven。apache。org/xsd/maven-4。0。0。xsd”> <!—— hystrix ——> <!—— 引入自己定義的api通用包,可以使用Dept部門Entity ——> <!—— 將微服務provider側註冊進eureka ——> <!—— actuator監控資訊完善 ——> <!—— 修改後立即生效,熱部署 ——> 3。參考microservicecloud-provider-dept-8001工程的java包中的類,將其microservicecloud-provider-dept-8001所有的類包都複製一份到microservicecloud-provider-dept-hystrix-8001的java包下,然後進行修改。 https:///s/1xRbciXhNDxPbTNZ9DBOrQg 密碼:fnio 1)。新增microservicecloud-provider-dept-hystrix-8001工程的application。yml檔案內容: sserver: port:8001 mybatis: config-location: classpath:mybatis/mybatis。cfg。xml #mybatis所在路徑 type-aliases-package: com。hhf。springcloud。entities #entity別名類 mapper-locations: - classpath:mybatis/mapper/**/*。xml #mapper對映檔案 spring: application: name: microservicecloud-dept datasource: type: com。alibaba。druid。pool。DruidDataSource driver-class-name: org。gjt。mm。mysql。Driver url: jdbc:mysql://localhost:3306/cloudDB01 username: root password: 520hhf dbcp2: min-idle: 5 initial-size: 5 max-total:5 max-wait-millis:200 eureka: client: #客戶端註冊進eureka服務列表內 service-url: defaultZone: http://eureka7001。com:7001/eureka/,http://eureka7002。com:7002/eureka/,http://eureka7003。com:7003/eureka/ instance: instance-id: microservicecloud-dept8001-hystrix #自定義服務名稱資訊 prefer-ip-address: true #訪問路徑可以顯示IP地址 info: app。name: atguigu-microservicecloud company。name: www。hhf。com build。artifactId: $project。artifactId$ build。version: $project。version$ 2)。修改microservicecloud-provider-dept-hystrix-8001工程下的DeptController類,把原先DeptController類裡面的所有方法以及屬性刪除,並新增以下內容: package com。hhf。springcloud。controller; import org。springframework。beans。factory。annotation。Autowired; import org。springframework。web。bind。annotation。PathVariable; import org。springframework。web。bind。annotation。RequestMapping; import org。springframework。web。bind。annotation。RequestMethod; import org。springframework。web。bind。annotation。RestController; import com。hhf。springcloud。entities。Dept; import com。hhf。springcloud。service。DeptService; import com。netflix。hystrix。contrib。javanica。annotation。HystrixCommand; @RestController publicclassDeptController { @Autowired private DeptService service = null; @RequestMapping(value=“/dept/get/{id}”,method=RequestMethod。GET) @HystrixCommand(fallbackMethod = “processHystrix_Get”) public Dept get(@PathVariable(“id”) Long id) { Dept dept = this。service。get(id); if(null == dept) { thrownew RuntimeException(“該ID:”+id+“沒有沒有對應的資訊”); } return dept; } public Dept processHystrix_Get(@PathVariable(“id”) Long id) { returnnew Dept()。setDeptno(id)。setDname(“該ID:”+id+“沒有沒有對應的資訊,null——@HystrixCommand”)。setDb_source(“no this database in MySQL”); } } 3)。修改主啟動類名,名為:DeptProvider8001_Hystrix_App並新增新註解@EnableCircuitBreaker @SpringBootApplication @EnableEurekaClient//本服務啟動後會自動註冊進eureka服務中 @EnableDiscoveryClient//服務發現 @EnableCircuitBreaker//對hystrixR熔斷機制的支援 public class DeptProvider8001_Hystrix_App { publicstaticvoidmain(String[] args) { SpringApplication。run(DeptProvider8001_Hystrix_App。class, args); } } 4。測試: 1)。啟動3個eureka叢集配置(microservicecloud-eureka-7001系列)。 2)。啟動microservicecloud-provider-dept-hystrix-8001的DeptProvider8001_Hystrix_App類。 3)。啟動microservicecloud-consumer-dept-80。 在瀏覽器中輸入: 如果在7001頁面中顯示了microservicecloud-dept8001-hystrix這個服務,說明成功!! 我們再來看消費者來呼叫: 在瀏覽器再輸入:http://localhost/consumer/dept/get/1 先看看能不能獲取到正確的資訊 如果可以,那麼我們再從瀏覽器輸入一個在資料庫裡面毫無id的資料,看看是不是能達到我們程式碼中寫的效果一樣: 在瀏覽器再輸入:http://localhost/consumer/dept/get/4444 如果沒有找到這個id值的資訊,那麼就頁面就會顯示一條資訊,如下圖所示: 這頁面顯示的資訊,就說明我們的熔斷呼叫成功!!! 總結:向呼叫方返回一個符合呼叫預期的,可處理的備選響應,快速返回錯誤的響應資訊。 https:///s/1xRbciXhNDxPbTNZ9DBOrQg 密碼:fnio 整體資源快不夠了,忍痛將某些服務先關掉,待渡過難關,再開啟回來。 服務降級處理是在客戶端實現完成的,與服務端沒有關係。 1。修改microservicecloud-api工程,service包下再建立一個類:DeptClientServiceFallbackFactory,並實現FallbackFactory這個介面。 package com。hhf。springcloud。service; import java。util。List; import org。springframework。stereotype。Component; import com。hhf。springcloud。entities。Dept; import feign。hystrix。FallbackFactory; @Component publicclassDeptClientServiceFallbackFactoryimplementsFallbackFactory { @Override public DeptClientService create(Throwable throwable) { returnnew DeptClientService() { @Override public Dept get(long id) { returnnew Dept()。setDeptno(id) 。setDname(“該ID:”+id+“沒有沒有對應的資訊,Consumer客戶端提供的降級資訊,此刻服務Provider已經關閉”) 。setDb_source(“no this database in MySQL”); } @Override public List { returnnull; } @Override publicbooleanadd(Dept dept) { returnfalse; } }; } } 2。再修改microservicecloud-api工程,在DeptClientService介面的註解@FeignClient中新增fallbackFactory屬性值 importorg。springframework。cloud。netflix。feign。FeignClient; importorg。springframework。web。bind。annotation。PathVariable; importorg。springframework。web。bind。annotation。RequestMapping; importorg。springframework。web。bind。annotation。RequestMethod; importcom。hhf。springcloud。entities。Dept; importjava。util。List; @FeignClient(value = “MICROSERVICECLOUD-DEPT”,fallbackFactory=DeptClientServiceFallbackFactory。class) public interface DeptClientService { @RequestMapping(value = “/dept/get/{id}”,method = RequestMethod。GET) public Dept get(@PathVariable(“id”) long id); @RequestMapping(value = “/dept/list”,method = RequestMethod。GET) public List @RequestMapping(value = “/dept/add”,method = RequestMethod。POST) public boolean add(Dept dept); } 3。在microservicecloud-consumer-dept-feign工程下新增application。yml檔案內容 新增內容為:(而其他內容不變) feign: hystrix: enabled: true https:///s/1xRbciXhNDxPbTNZ9DBOrQg 密碼:fnio 1)。啟動3個eureka叢集配置(microservicecloud-eureka-7001系列)。 2)。microservicecloud-provider-dept-8001啟動。 3)。microservicecloud-consumer-dept-feign啟動。 4)。在瀏覽器中輸入:http://localhost/consumer/dept/get/1 進行測試。 效果圖: 5)。故意關閉微服務microservicecloud-provider-dept-8001。 6)。再瀏覽器中輸入:http://localhost/consumer/dept/get/1 進行重新測試。 效果圖: 此時服務端provider已經down了,但是我們做了服務降級處理,讓客戶端在服務端不可用時也會獲得提示資訊而不會掛起耗死伺服器。 除了隔離依賴服務的呼叫以外,Hystrix還提供了準實時的呼叫監控(Hystrix Dashboard),Hystrix會持續地記錄所有透過Hystrix發起的請求的執行資訊,並以統計報表和圖形的形式展示給使用者,包括每秒執行多少請求多少成功,多少失敗等。 Netflix透過hystrix-metrics-event-stream專案實現了對以上指標的監控。Spring Cloud也提供了Hystrix Dashboard的整合,對監控內容轉化成視覺化介面。 1。在總父工程microservicecloud下新建工程microservicecloud-consumer-hystrix-dashboard子工程。 2。在microservicecloud-consumer-hystrix-dashboard工程下的pom檔案裡面新增jar包: <?xml version=“1。0” encoding=“UTF-8”?> xmlns:xsi=“http://www。w3。org/2001/XMLSchema-instance” xsi:schemaLocation=“http://maven。apache。org/POM/4。0。0 http://maven。apache。org/xsd/maven-4。0。0。xsd”> <!—— 自己定義的api ——> <!—— 修改後立即生效,熱部署 ——> <!—— Ribbon相關 ——> <!—— feign相關 ——> <!—— hystrix和 hystrix-dashboard相關——> 3。在microservicecloud-consumer-hystrix-dashboard工程下的application。yml檔案裡面新增配置: server: port: 9001 4。建立主啟動類,名為:DeptConsumer_DashBoard_App 並在方法上添加註解@EnableHystrixDashboard @SpringBootApplication @EnableHystrixDashboard public class DeptConsumer_DashBoard_App { publicstaticvoidmain(String[] args) { SpringApplication。run(DeptConsumer_DashBoard_App。class,args); } } 好,我們開始進行測試: 1)。啟動microservicecloud-consumer-hystrix-dashboard該微服務監控消費端。 在瀏覽器中輸入:http://localhost:9001/hystrix 進行測試。 效果圖: 出現以下效果說明成功!!! 2)。啟動3個eureka叢集配置(microservicecloud-eureka-7001系列)。 3)。啟動microservicecloud-provider-dept-hystrix-8001。 1。在瀏覽器中輸入:http://localhost:8001/dept/get/1 進行測試 2。再從瀏覽器中輸入:http://localhost:8001/hystrix。stream 進行測試 效果圖: 3)。我們把上面的效果圖以圖形化的介面進行展示,那麼我們回到 http://localhost:9001/hystrix頁面中。 然後在Hystrix Dashboard下面的一個框裡輸入 http://localhost:8001/hystrix。stream 這個網址。 效果圖1: 然後點選那個按鈕進入一個圖形化介面。 效果圖2: 目前我們9001工程監控8001工程。 然後我們來使用這個監控頁面,在頁面的左邊有一個1圈和1線和7色的圖,我們來試著狂重新整理http://localhost:8001/dept/get/1這個頁面,然後再回到圖形化監控頁面的變化。 說明:實心圓:共有兩種含義。它透過顏色的變化代表了例項的健康程度,它的健康度從綠色<黃色<橙色<紅色遞減。該實心圓除了顏色的變化之外,它的大小也會根據例項的請求流量發生變化,流量越大該實心圓就越大。所以透過該實心圓的展示,就可以在大量的例項中快速的發現故障例項和高壓力例項。 曲線:用來記錄2分鐘內流量的相對變化,可以透過它來觀察到流量的上升和下降趨勢。 效果圖1:狂重新整理以後就再迅速回到圖形化監控頁面來檢視變化。 效果圖2:看到監控頁面的變化了吧? Hystrix是什麼? 服務的熔斷 其中路由功能負責將外部請求轉發到具體的微服務例項上,是實現外部訪問統一入口的基礎而過濾器功能則負責對請求的處理過程進行干預,是實現請求校驗、服務聚合等功能的基礎。 Zuul和Eureka進行整合,將Zuul自身註冊為Eureka服務治理下的應用,同時從Eureka中獲得其他微服務的訊息,也即以後的訪問微服務都是透過Zuul跳轉後獲得。 microservicecloud-provider-dept-hystrix-8001工程修改和新增內容如下: 提供=代理+路由+過濾三大功能。 服務的降級 1。新建子工程Module模組microservicecloud-zuul-gateway-9527。 2。在microservicecloud-zuul-gateway-9527工程的pom檔案新增jar包。 <?xml version=“1。0” encoding=“UTF-8”?> xmlns:xsi=“http://www。w3。org/2001/XMLSchema-instance” xsi:schemaLocation=“http://maven。apache。org/POM/4。0。0 http://maven。apache。org/xsd/maven-4。0。0。xsd”> <!—— zuul路由閘道器 ——> <!—— actuator監控 ——> <!—— hystrix容錯——> <!—— 日常標配 ——> <!—— 熱部署外掛 ——> 3。在microservicecloud-zuul-gateway-9527工程的resources資原始檔包下建立application,yml檔案並新增以下內容: server: port: 9527 spring: application: name: microservicecloud-zuul-gateway eureka: client: service-url: defaultZone: http://eureka7001。com:7001/eureka,http://eureka7002。com:7002/eureka,http://eureka7003。com:7003/eureka instance: instance-id: gateway-9527。com prefer-ip-address: true info: app。name: hhf-microcloud company。name: www。hhf。com build。artifactId: $project。artifactId$ build。version: $project。version$ 4。在我們電腦的hosts檔案裡面新增如下域名: 127。0。0。1myzuul。com 5。在java包下建立主啟動類,名為:Zuul_9527_StartSpringCloudApp @SpringBootApplication @EnableZuulProxy public class Zuul_9527_StartSpringCloudApp { publicstaticvoidmain(String[] args) { SpringApplication。run(Zuul_9527_StartSpringCloudApp。class, args); } } 6。測試: 1)。啟動3個eureka(microservicecloud-eureka-7001系列)。 2)。啟動microservicecloud-provider-dept-8001工程。 3)。啟動microservicecloud-zuul-gateway-9527工程。 在瀏覽器輸入:http://eureka7001。com:7001/ 來看看初步的配置 效果圖1: 4)。先不用路由來測試,在瀏覽器輸入:http://localhost:8001/dept/get/2 5)。啟動路由來測試,在瀏覽器輸入:http://myzuul。com:9527/microservicecloud-dept/dept/get/2 透過閘道器也可以訪問到我們的微服務。 4.測試: 我們對http://myzuul。com:9527/microservicecloud-dept/dept/get/2這個頁面做一下路由訪問對映的規則 在microservicecloud-zuul-gateway-9527工程下修改以下內容: 1。在application。yml檔案裡面新增以下內容(其他不變) zuul: routes: mydept。serviceId: microservicecloud-dept mydept。path: /mydept/** 服務監控hystrixDashboard 1)。重新啟動microservicecloud-zuul-gateway-9527工程 2)。在瀏覽器輸入: http://myzuul。com:9527/mydept/dept/get/1 進行測試 最終結果還是能訪問成功(這裡就不截圖了)。 3)。再從瀏覽器中輸入:http://myzuul。com:9527/microservicecloud-dept/dept/get/2 進行測試 microservicecloud-dept這個名字結果也還是能訪問成功,那麼這個就有點不太安全了,那麼最好是單入口單出口。那麼我們用代理名字來對外暴露該服務。 2)。在application。yml檔案裡面的zuul下面再新增一句內容(其他不變) ignored-services: microservicecloud-dept 完整配置: zuul: ignored-services: microservicecloud-dept #只是添加了這一句!! routes: mydept。serviceId: microservicecloud-dept mydept。path: /mydept/** zuul路由閘道器 1)。重新啟動microservicecloud-zuul-gateway-9527工程 2)。在瀏覽器輸入: http://myzuul。com:9527/mydept/dept/get/1 進行測試 最終結果還是能訪問成功(這裡就不截圖了)。 3)。再從瀏覽器中輸入: http://myzuul。com:9527/microservicecloud-dept/dept/get/2 進行測試 結果卻訪問不到了,原因是原路徑已經被我們封了!!! 效果圖: Zuul包含了對請求的路由和過濾兩個最主要的功能: 戳下面的 注意:Zuul服務最終還是會註冊進Eureka。 !