歡迎來到菜鳥SpringCloud實戰入門系列(SpringCloudForNoob),該系列經過層層遞進的實戰視角,來一步步學習和理解SpringCloud。html
本系列適合有必定Java以及SpringBoot基礎的同窗閱讀。git
每篇文章末尾都附有本文對應的Github源代碼,方便同窗調試。github
Github倉庫地址:web
你能夠經過如下兩種途徑查看菜鳥SpringCloud實戰入門系列:spring
前文回顧:express
關於熔斷器的解釋,這裏引用一大段:後端
熔斷器適用於實現快速失敗,若是它在一段時間內偵測到許多相似的錯誤,會強迫其之後的多個調用快速失敗,再也不訪問遠程服務器,從而防止應用程序不斷地嘗試執行可能會失敗的操做,使得應用程序繼續執行而不用等待修正錯誤,或者浪費CPU時間去等到長時間的超時產生。熔斷器也可使應用程序可以診斷錯誤是否已經修正,若是已經修正,應用程序會再次嘗試調用操做。緩存
熔斷器模式就像是那些容易致使錯誤的操做的一種代理。這種代理可以記錄最近調用發生錯誤的次數,而後決定使用容許操做繼續,或者當即返回錯誤。 熔斷器開關相互轉換的邏輯以下圖:安全
熔斷器就是保護服務高可用的最後一道防線。
Hystrix特性
1.斷路器機制
斷路器很好理解, 當Hystrix Command請求後端服務失敗數量超過必定比例(默認50%), 斷路器會切換到開路狀態(Open). 這時全部請求會直接失敗而不會發送到後端服務. 斷路器保持在開路狀態一段時間後(默認5秒), 自動切換到半開路狀態(HALF-OPEN). 這時會判斷下一次請求的返回狀況, 若是請求成功, 斷路器切回閉路狀態(CLOSED), 不然從新切換到開路狀態(OPEN). Hystrix的斷路器就像咱們家庭電路中的保險絲, 一旦後端服務不可用, 斷路器會直接切斷請求鏈, 避免發送大量無效請求影響系統吞吐量, 而且斷路器有自我檢測並恢復的能力.
2.Fallback
Fallback至關因而降級操做. 對於查詢操做, 咱們能夠實現一個fallback方法, 當請求後端服務出現異常的時候, 可使用fallback方法返回的值. fallback方法的返回值通常是設置的默認值或者來自緩存.
3.資源隔離
在Hystrix中, 主要經過線程池來實現資源隔離. 一般在使用的時候咱們會根據調用的遠程服務劃分出多個線程池. 例如調用產品服務的Command放入A線程池, 調用帳戶服務的Command放入B線程池. 這樣作的主要優勢是運行環境被隔離開了. 這樣就算調用服務的代碼存在bug或者因爲其餘緣由致使本身所在線程池被耗盡時, 不會對系統的其餘服務形成影響. 可是帶來的代價就是維護多個線程池會對系統帶來額外的性能開銷. 若是是對性能有嚴格要求並且確信本身調用服務的客戶端代碼不會出問題的話, 可使用Hystrix的信號模式(Semaphores)來隔離資源.
依然使用上一章創建的子模塊:Service-Feign
pom文件不須要變化,由於spring-cloud-starter-openfeign已經自帶了Hystrix。
修改配置文件application.yml,增長以下:
feign:
hystrix:
enabled: true
複製代碼
在我這裏,因爲Springboot使用了2.0.3,引入的是openfeign,因此出現了:
起初覺得這條指令沒法生效,折騰了以後才發現是生效的。
推測是openfeign的問題,不是spring boot 1.X的spring-cloud-starter-feign,IDEA判斷失誤了。
接着新建類ServiceHiHystrix繼承ServiceHi接口,裏面實現了失敗下的返回信息:
import org.springframework.stereotype.Component;
@Component
public class ServiceHiHystrix implements ServiceHi {
@Override
public String sayHiFromServiceHi(String name) {
return "hello" + name +", this message send failed";
}
}
複製代碼
更改ServiceHi接口,添加上fallback類爲剛纔新建的類:
@FeignClient(value = "service-hi", fallback = ServiceHiHystrix.class)
複製代碼
大功告成,啓動server-feign,eureka-hi和eureka測試:
打開:http://localhost:8765/hello/rude3knife
接着,關掉服務提供者eureka-hi,來模擬服務宕機的狀況,從新訪問:http://localhost:8765/hello/rude3knife
返回了新建的錯誤信息。
Hystrix-dashboard是一款針對Hystrix進行實時監控的工具,經過Hystrix Dashboard咱們能夠在直觀地看到各Hystrix Command的請求響應時間, 請求成功率等數據。
咱們只須要在上一章中的server-feign模塊繼續修改,由於上一章已經在該模塊加了熔斷器。
首先添加依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<!--spring boot 1.X:spring-cloud-starter-hystrix-->
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<!--spring boot 1.X:spring-cloud-starter-hystrix-dashboard-->
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
複製代碼
啓動類修改:
@EnableHystrixDashboard
@EnableCircuitBreaker
複製代碼
啓動工程訪問:
http://localhost:8765/hystrix,將會看到以下界面:
圖中會有一些提示:
大概意思就是若是查看默認集羣使用第一個url,查看指定集羣使用第二個url,單個應用的監控使用最後一個,咱們暫時只演示單個應用的因此在輸入框中輸入: http://localhost:8765/hystrix.stream ,輸入以後點擊 monitor,進入頁面。
若是沒有請求會先顯示Loading ...,訪問http://localhost:9001/hystrix.stream 也會不斷的顯示ping。
請求服務http://localhost:8765/hello/rude3knife,就能夠看到監控的效果了,首先訪問http://localhost:8765/hystrix.stream,顯示以下:
出錯了!
隨機谷歌了下問題,網友給出了問題解決方案:
答主經過查看源碼後給出的解決方案是:
評論區給出更爲方便且優雅的方案:
在配置文件中加入management.endpoints.web.exposure.include=*,將端口暴露就不須要聲明bean了,訪問地址要變一下/actuator/hystrix.stream
因而咱們在yml中加入:
# 熔斷器DashBoard: actuator在boot2.0調整後開關web端點的配置,*表明開啓全部
management:
endpoints:
web:
exposure:
include: "*"
複製代碼
從新運行模塊,而後在網址一欄輸入:
http://localhost:8765/actuator/hystrix.stream
頁面會不停顯示Loading,不用慌,不顯示Unable to connect to Command Metric Stream.了。顯示Loading是由於由於尚未請求過來。
以後咱們嘗試發一次請求,在地址欄對server-feign的8765端口發送請求:
http://localhost:8765/hello/1232312
再來看以前的頁面,大功告成。
到此單個應用的熔斷監控已經完成。
可是隻使用Hystrix Dashboard的話, 你只能看到單個應用內的服務信息, 這明顯不夠. 咱們須要一個工具能讓咱們彙總系統內多個服務的數據並顯示到Hystrix Dashboard上, 這個工具就是Turbine.
在複雜的分佈式系統中,相同服務的節點常常須要部署上百甚至上千個,不少時候,運維人員但願可以把相同服務的節點狀態以一個總體集羣的形式展示出來,這樣能夠更好的把握整個系統的狀態。
注意:
爲了演示Turbine,在這裏從新新建一個子模塊,名爲hystrix-dashboard-turbine,建立步驟請看以前的第一章。
建立新模塊做爲單獨的監控節點模塊,是由於演示dashboard的時候是耦合在了server-feign中,而Turbine須要同時監控多個服務消費者,把他耦合在一個消費者裏顯得不合時宜。
建立後,pom.xml中引入:
<dependency>
<groupId>org.springframework.cloud</groupId>
<!--spring boot 1.X:spring-cloud-starter-hystrix-dashboard-->
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-turbine</artifactId>
</dependency>
複製代碼
啓動類中@EnableTurbine和@EnableHystrixDashboard:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.netflix.turbine.EnableTurbine;
@SpringBootApplication
@EnableTurbine
@EnableHystrixDashboard
public class HystrixDashboardTurbineApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardTurbineApplication.class, args);
}
}
複製代碼
yml中:
server:
# 服務端口號
port: 8767
spring:
application:
# 服務名,即serviceId
name: hystrix-dashboard-turbine
eureka:
client:
serviceUrl:
# 安全認證的服務註冊中心地址
defaultZone: http://localhost:8761/eureka
# 熔斷器turbine
turbine:
aggregator:
cluster-config: default
cluster-name-expression: new String("default")
app-config: SERVICE-FEIGN, SERVICE-FEIGN-2
複製代碼
代碼重點:
完成這些步驟後,咱們還須要調整下服務提供者,咱們須要兩個服務提供者同時運行。
將8765(SERVICE-FEIGN)的服務提供者改成8766,名稱改成:SERVICE-FEIGN-2,運行起來,別忘了在運行設置中設置容許多個實例運行。修改後的SERVICE-FEIGN的yml是:
server:
# 服務端口號
port: 8766
spring:
application:
# 服務名,即serviceId
name: service-feign-2
eureka:
client:
serviceUrl:
# 安全認證的服務註冊中心地址
defaultZone: http://localhost:8761/eureka
# 熔斷器設置
feign:
hystrix:
enabled: true
# 熔斷器DashBoard: actuator在boot2.0調整後開關web端點的配置,*表明開啓全部
management:
endpoints:
web:
exposure:
include: "*"
複製代碼
運行後結構如圖:
咱們訪問:訪問 http://localhost:8767/turbine.stream
能夠看到ping的信息流,這時說明8767正在不斷ping指定的兩個服務
進行圖形化監控查看,輸入:http://localhost:8767/hystrix ,返回酷酷的小熊界面,輸入: http://localhost:8767/turbine.stream ,而後點擊 Monitor Stream ,能夠看到出現了監控列表:
咦?爲啥只有一個監控呢,說好的聚合監控列表呢。
這裏有個坑,或者說是理解上的誤區:
監控不一樣的服務熔斷,首先得是不一樣的rpc調用,也就是消費者的熔斷函數要是兩個不一樣的,或者,消費者去調用的是兩個不一樣的服務提供者!這樣纔會有多個監控表。否則,有何意義?
想明白這一步,你就應該知道怎麼把多個表弄出來了。
你須要讓消費者有一個:
修改server-feign子模塊
@FeignClient(value = "service-hi-2", fallback = ServiceHiHystrix.class)
public interface ServiceHi {
/**
* <p>經過Feign僞Http客戶端調用service-hi提供的服務</p>
* @author hanchao 2018/5/19 17:59
**/
@GetMapping("/hi/{name}")
String sayHiFromServiceHi2(@PathVariable(value = "name") String name);
}
複製代碼
@Component
public class ServiceHiHystrix implements ServiceHi {
@Override
public String sayHiFromServiceHi2(String name) {
return "hello" + name +", this message send failed. By Hystrix.";
}
}
複製代碼
return serviceHi.sayHiFromServiceHi2
@RestController
public class HelloController {
/** 注入服務"service-hi"的Feign客戶端ServiceHi */
@Autowired
private ServiceHi serviceHi;
/**
* 調用Feign客戶端提供的服務,自帶負載均衡
* @param name
* @return
*/
@GetMapping("/hello/{name}")
public String sayHi(@PathVariable String name){
//調用Feign客戶端ScheduleServiceHi的接口
return serviceHi.sayHiFromServiceHi2(name);
}
}
複製代碼
這樣改完後,重啓這個8766的服務消費者
結構依然不變:
咱們獲得了:
這裏確實比較難理解哈,坑了我很久。
springcloud(四):熔斷器Hystrix
www.ityouknow.com/springcloud…
springcloud(五):熔斷監控Hystrix Dashboard和Turbine
www.ityouknow.com/springcloud…
菜鳥SpringCloud實戰入門專欄全導航:經過如下兩種途徑查看
我是蠻三刀把刀,後端開發。主要關注後端開發,數據安全,爬蟲等方向。
來微信和我聊聊:yangzd1102
Github我的主頁:
同步更新公衆號及如下所有博客:
1. Csdn
2. 知乎
3. 掘金
4. 簡書
若是文章對你有幫助,不妨收藏起來並轉發給您的朋友們~