目錄
- 第一章 Hystrix介紹
- 1.1、什么是Hystrix
- 1.2、為啥用Hystrix
- 第二章 Hystrix三大概念
- 2.1、服務降級含義
- 2.2、服務熔斷含義
- 2.3、服務限流含義
- 第三章 Hystrix入門案例
- 3.1、基礎準備作業
- 3.2、服務降級學習
- 3.2.1、單個方法降級
- 3.2.2、多個方法降級
- 3.2.3、全域統一處理
- 3.3、服務熔斷學習
- 3.3.1、服務熔斷演示
- 3.3.2、服務熔斷型別
- 3.3.3、服務熔斷條件
- 3.3.4、服務熔斷設定
- 3.4、服務限流學習
- 第四章 Hystrix服務監控
- 4.1、監控概述
- 4.2、工程搭建
- 4.3、圖表說明
- 第五章 Hystrix配置詳解
配套資料,免費下載
鏈接:https://pan.baidu.com/s/1la_3-HW-UvliDRJzfBcP_w
提取碼:lxfx
復制這段內容后打開百度網盤手機App,操作更方便哦
第一章 Hystrix介紹
1.1、什么是Hystrix
Hystrix是由Netflix開源的一個服務隔離組件,通過服務隔離來避免由于依賴延遲、例外,引起資源耗盡導致系統不可用的解決方案,
1.2、為啥用Hystrix
在分布式系統,我們一定會依賴各種服務,那么這些個服務一定會出現失敗的情況,Hystrix就是這樣的一個工具,它通過提供了邏輯上延時和錯誤容忍的解決力來協助我們完成分布式系統的互動,Hystrix通過分離服務的呼叫點,阻止錯誤在各個系統的傳播,并且提供了錯誤回呼機制,這一系列的措施提高了系統的整體服務彈性,
第二章 Hystrix三大概念
2.1、服務降級含義
當一個目標服務執行時間過長,為了不讓客戶端無意義盲目等待,此時會立刻回傳一個友好提示,比如:服務器過忙,請稍后再試,這就是服務降級,程式運行例外、程式運行超時、服務熔斷都會觸發服務降級、執行緒池/信號量打滿也會觸發服務降級,
2.2、服務熔斷含義
這種模式主要是參考電路熔斷,如果一條線路電壓過高,保險絲會熔斷,防止火災,放到我們的系統中,如果某個目標服務呼叫慢或者有大量超時,此時,熔斷該服務的呼叫,對于后續呼叫請求,不在繼續呼叫目標服務,直接回傳,快速釋放資源,如果目標服務情況好轉則恢復呼叫,
2.3、服務限流含義
上述兩種模式都屬于出錯后的容錯處理機制,而限流模式則可以稱為預防模式,限流模式主要是提前對各個型別的請求設定最高的QPS閾值,若高于設定的閾值則對該請求直接回傳,不再呼叫后續資源,這種模式不能解決服務依賴的問題,只能解決系統整體資源分配問題,因為沒有被限流的請求依然有可能造成雪崩效應,
第三章 Hystrix入門案例
3.1、基礎準備作業
我們接下來的所有操作均是在OpenFegin最后完成的工程上進行操作,相關代碼請到配套資料中尋找,

(1)我們接下來的所有操作均在service-consumer9002工程中進行,請在pom.xml中添加Hystrix的依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
(2)修改application.yaml,將Ribbon的超時時間全部注釋,方便接下來測驗
#ribbon:
# ReadTimeout: 5000
# ConnectTimeout: 5000
(3)修改service-provider8001的ProductController的findByPid方法,根據pid分別模擬了運行正常、運行錯誤、超時等情況
@RequestMapping("/provider/product/findByPid")
public String findByPid(@RequestParam("pid") Integer pid) throws InterruptedException {
//模擬:pid如果小于0說明出錯
if (pid < 0) { throw new RuntimeException("***** pid 不能負數 *****"); }
//模擬:pid如果等于0說明業務正常
if (pid == 0) { System.out.println("***** pid 業務正常 *****"); }
//模擬:pid如果大于0說明業務超時
if (pid > 0) { Thread.sleep(3000); }
//結果:回傳服務埠+方法+執行緒名
return "8001 findByPid " + Thread.currentThread().getName();
}
(4)修改service-provider8002的ProductController的findByPid方法,根據pid分別模擬了運行正常、運行錯誤、超時等情況
@RequestMapping("/provider/product/findByPid")
public String findByPid(@RequestParam("pid") Integer pid) throws InterruptedException {
//模擬:pid如果小于0說明出錯
if (pid < 0) { throw new RuntimeException("***** pid 不能負數 *****"); }
//模擬:pid如果等于0說明業務正常
if (pid == 0) { System.out.println("***** pid 業務正常 *****"); }
//模擬:pid如果大于0說明業務超時
if (pid > 0) { Thread.sleep(3000); }
//結果:回傳服務埠+方法+執行緒名
return "8002 findByPid " + Thread.currentThread().getName();
}
(5)依次啟動如下程式
- eureka-server7001
- eureka-server7002
- service-provider8001
- service-provider8002
- service-consumer9002
(6)依次輸入網址來查看
呼叫服務出錯:http://localhost:9002/consumer/product/findByPid?pid=-1

呼叫服務正常:http://localhost:9002/consumer/product/findByPid?pid=0

呼叫服務超時:http://localhost:9002/consumer/product/findByPid?pid=1

正因為有上述故障或不佳表現,才有我們的降級/熔斷/限流等技術誕生,
3.2、服務降級學習
3.2.1、單個方法降級
注意:服務降級既可以放到
服務提供端,也可以放到服務消費端,因為服務消費端的controller是呼叫的服務提供端的controller,都是controller,那就都可以用,沒有什么區別,不過需要注意一點就是第(2)步的配置,服務提供端是不需要配置這一段內容的,服務消費端就必須要提供這一段配置了,
(1)在入口類中使用@EnableCircuitBreaker注解或@EnableHystrix開啟斷路器功能,也可以使用一個名為@SpringCloudApplication的注解代替主類上的三個注解(@SpringBootApplication、@EnableDiscoveryClient(默認自動開啟)、@EnableCircuitBreaker),推薦@EnableHystrix,修改后如下:
@SpringBootApplication
@EnableFeignClients
@EnableHystrix
public class ServiceConsumer9002Application {
public static void main(String[] args) {
SpringApplication.run(ServiceConsumer9002Application.class);
}
}
(2)在application.yaml中新增一段代碼:
feign:
hystrix:
enabled: true #如果處理自身的容錯就開啟,如果服務降級放到服務提供端不需要配置這一段代碼
(3)在對應的控制器類ProductController上你所要對哪個方法進行服務降級,就對哪個方法進行特殊處理,這里我對findByPid進行處理,處理代碼如下:
@HystrixCommand(fallbackMethod = "findByPidFallback", commandProperties = {
/*這里用來放常見的配置,比如:該方法的超時時間是多少*/
@HystrixProperty(name = "execution.timeout.enabled", value = "true"),
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")
})
@RequestMapping("/consumer/product/findByPid")
public String findByPid(@RequestParam("pid") Integer pid) {
return productFeignService.findByPid(pid);
}
/**
* 服務降級方法,相當于findByPid方法的默認回傳值
* 由上邊的從資料庫中查出來的動態資料 -》 服務出錯呼叫這個降級方法回傳默認值的程序就是服務降級
*
* @param pid
* @return 回傳值型別要和原方法保持一致
*/
public String findByPidFallback(@RequestParam("pid") Integer pid) {
return "發生故障,服務降級 ...";
}
(4)重啟service-consumer9002,因為有時候熱部署并不能很好的幫我們自動重啟服務,手動重啟保險
(5)依次輸入網址來查看
呼叫服務出錯:http://localhost:9002/consumer/product/findByPid?pid=-1

呼叫服務正常:http://localhost:9002/consumer/product/findByPid?pid=0

呼叫服務超時:http://localhost:9002/consumer/product/findByPid?pid=1

注意:hystrix 默認超時時間是 1000 毫秒,如果你后端的回應超過此時間,就會觸發服務降級方法fallback,而修改這個默認時間通常有兩種解決辦法:
第一種:注解屬性修改
@RequestMapping("/XXX/XXX") @HystrixCommand(fallbackMethod = "findByPidFallback", commandProperties = { /*這里用來放常見的配置,比如:該方法的超時時間是多少*/ @HystrixProperty(name = "execution.timeout.enabled", value = "true"),//默認為true,可以不配置 @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000") })第二種:組態檔配置
ribbon.ReadTimeout=6000 ribbon.ConnectTimeout=3000 hystrix.command.default.execution.timeout.enabled=true hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000這里有個坑需要注意一下:
如果
hystrix.command.default.execution.timeout.enabled為true,則會有兩個執行方法超時的配置,一個就是ribbon的ReadTimeout,一個就是斷路器hystrix的timeoutInMilliseconds,此時誰的值小誰生效;如果
hystrix.command.default.execution.timeout.enabled為false,則斷路器不進行hystrix的超時熔斷,而是根據ribbon的ReadTimeout拋出的例外而熔斷,而ribbon的ConnectTimeout,配置的是請求服務的超時時間,除非服務找不到,或者網路原因,這個時間才會生效;ribbon.ReadTimeout=6000 ribbon.ConnectTimeout=3000
3.2.2、多個方法降級
雖然我們可以使用上邊那種方式,一個一個的給所有的方法添加服務降級的處理方法,但是,這樣一來,你的控制層會多很多跟業務邏輯沒有關系的代碼,增加了很多代碼,我們也成為代碼膨脹,有沒有一種方式,既可以處理每一個方法給他添加服務降級方法,又能跟控制器類中的方法進行解耦合,我們可以使用Fegin跟Hystrix相結合的方式來進行處理,
(1)我們打開ProductFeignService,會發現這里邊的代碼不就是Feign用于呼叫遠程服務提供者所定義的介面方法,我們第一步就是重新撰寫一個類來繼承這個介面,因為這個介面中的方法不就是我們ProductController中呼叫的方法嗎,
com.caochenlei.service.impl.ProductFeignServiceFallBackImpl
@Component
public class ProductFeignServiceFallBackImpl implements ProductFeignService {
@Override
public List<Product> findAll() {
return Arrays.asList(
new Product(1, "小米手機-服務降級 ...", 1000.0D, 100),
new Product(2, "華為手機-服務降級 ...", 2000.0D, 200),
new Product(3, "蘋果手機-服務降級 ...", 3000.0D, 300)
);
}
@Override
public String findByPid(Integer pid) {
return "findByPid 服務降級 ...";
}
}
(2)你得告訴ProductFeignService當呼叫遠程方法失敗后,你應該去哪一個類來找相對應的服務降級fallback來進行服務降級處理,
com.caochenlei.service.ProductFeignService
@Component
@FeignClient(value = "SERVICE-PROVIDER", fallback = ProductFeignServiceFallBackImpl.class)
public interface ProductFeignService {
...
}
(3)重新啟動service-consumer9002,啟動完成以后,手動強制關閉service-provider8001、service-provider8002來模擬服務提供者端宕機
(4)依次輸入網址來查看
查看商品串列:http://localhost:9002/consumer/product/findAll

呼叫服務出錯:http://localhost:9002/consumer/product/findByPid?pid=-1

呼叫服務正常:http://localhost:9002/consumer/product/findByPid?pid=0

呼叫服務超時:http://localhost:9002/consumer/product/findByPid?pid=1

從上邊的四個測驗中不難看出,如果當前方法上已經增加了一個@HystrixCommand,則會有優先執行自己定義的,如果自己沒有定義服務降級的方法,則會走ProductFeignServiceFallBackImpl中定義的方法,這樣一來就實作了業務邏輯和fallback解耦操作了,
3.2.3、全域統一處理
我們不確定我們自己的ProductController中所寫的方法一定是服務提供者中的方法,我們也有可能有自己的方法,那樣的話,使用上邊的處理方式,好像似憾訓有點問題,我們總不能把我們自己特有的方法也寫到ProductFeignService這個介面中吧,你不寫到這個介面中,ProductFeignServiceFallBackImpl就沒辦法實作對應方法的fallback服務降級方法,你當然可以使用第一種的一個一個的使用注解@HystrixCommand來配,但是萬一有100多個呢,那你不傻眼了嗎,有沒有一種可以統一處理全域的服務降級方法,這個全域就是,如果,你自己有指定的我就用你指定的(多個方法降級的也算指定的),你沒有指定,都交給我來處理,具體的做法請參考如下步驟:
(1)首先我們需要在service-consumer9002的ProductController中添加2個獨有的控制器方法,并標注@HystrixCommand注解,代碼如下:
@HystrixCommand
@RequestMapping("/consumer/product/findOne")
public String findOne() {
int a = 1 / 0;//模擬例外
return "findOne 正常方法 ...";
}
@HystrixCommand
@RequestMapping("/consumer/product/findTwo")
public String findTwo() {
int a = 1 / 0;//模擬例外
return "findTwo 正常方法 ...";
}
(2)在service-consumer9002的ProductController中撰寫一個全域服務降級的fallback方法,代碼如下:
public String GlobalFallbackMethod(){
return "全域服務降級fallback ...";
}
(3)在service-consumer9002的ProductController上標注一個默認配置的注解,代碼如下:
@RestController
@DefaultProperties(defaultFallback = "GlobalFallbackMethod") //全域的
public class ProductController {
...
}
(4)重新啟動service-consumer9002
(5)依次輸入網址來查看
查看商品串列:http://localhost:9002/consumer/product/findAll

呼叫服務出錯:http://localhost:9002/consumer/product/findByPid?pid=-1

呼叫服務正常:http://localhost:9002/consumer/product/findByPid?pid=0

呼叫服務超時:http://localhost:9002/consumer/product/findByPid?pid=1

findOne:http://localhost:9002/consumer/product/findOne

findTwo:http://localhost:9002/consumer/product/findTwo

注意:這個全域服務降級的fallback方法也不是隨便寫的,至少你的回傳值型別都應該和原方法保持一致,有人可能會問,我有的查詢一件商品,有的查詢商品串列,這怎么可能回傳一致,那這種方法是不是沒有效果了,我們可以寫一個回傳結果包裝類,來統一處理回傳結果,我這里給大家提供一種常見的包裝類形式,僅供參考:
/** * 統一處理回傳結果 * * @author CaoChenLei */ @Data @NoArgsConstructor @AllArgsConstructor public class Result implements Serializable { private Integer code;//狀態碼,比如:200 private String msg;//訊息標題,比如:查詢商品串列成功 private Object data;//這個data里邊就是具體回傳的資料,什么型別都支持,如果沒有資料就回傳null }
3.3、服務熔斷學習
3.3.1、服務熔斷演示
(1)重新啟動service-provider8001,service-provider8002,服務提供者
(2)首先訪問:http://localhost:9002/consumer/product/findByPid?pid=0,我們發現可以正常訪問
(3)再次訪問:http://localhost:9002/consumer/product/findByPid?pid=-1,快速訪問10次錯誤的,然后在訪問一次正確的,你會發現正確的不能訪問了(能訪問再多重繪幾次,反復嘗試),然后你就不停的訪問正確的,發現一會正確的又可以訪問了,這個就是服務的熔斷
3.3.2、服務熔斷型別
- 熔斷打開:請求不再進行呼叫當前服務,內部設定時鐘一般為MTTR(平均故障處理時間),當打開時長達到所設時鐘則進入熔斷狀態
- 熔斷關閉:熔斷關閉不會對服務進行熔斷
- 熔斷半開:部分請求根據規則呼叫當前服務,如果請求成功且符合規則,則認為當前服務恢復正常,關閉熔斷
3.3.3、服務熔斷條件
- 當滿足一定閥值的時候(默認10秒內超過20個請求次數)
- 當失敗率達到一定的時候(默認10秒內超過50%請求失敗)
- 到達以上閥值,斷路器將會開啟
- 當開啟的時候,所有請求都不會進行轉發
- 一段時間之后(默認是5秒),這個時候斷路器是半開狀態,會讓其中一個請求進行轉發,如果成功,斷路器會關閉,若失敗,繼續開啟,重復4和5
3.3.4、服務熔斷設定

3.4、服務限流學習
hystrix限流就是限制你某個微服務的使用量(可用執行緒數、信號量),hystrix通過執行緒池的方式來管理微服務的呼叫,它默認是一個執行緒池(大小10個) 管理你的所有微服務,你可以給某個微服務開辟新的執行緒池:
(1)在service-consumer9002的ProductController添加如下代碼:
/**
* threadPoolKey:是執行緒池唯一標識,hystrix會使用該標識來計數,看執行緒占用是否超過了,超過了就會直接降級該次呼叫
* 這里coreSize給他值為2,那么假設你這個方法呼叫時間是1s執行完,那么在1s內如果有超過2個請求進來的話,剩下的請求則全部降級
* 其中maxQueueSize是一個執行緒佇列,里面只能放1個請求執行緒,本來執行緒數有2個,佇列里面允許放一個,那么總共只能有3個請求執行緒執行,如果超過了就會限流
*/
@HystrixCommand(fallbackMethod = "miaoShaFallback",
threadPoolKey = "miaoSha",
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "2"),
@HystrixProperty(name = "maxQueueSize", value = "1")
})
@RequestMapping("/consumer/product/miaoSha")
public String miaoSha() throws InterruptedException {
Thread.sleep(500);//模擬業務邏輯消耗的時間
return "恭喜你,搶到了,^_^";
}
public String miaoShaFallback() {
return "秒殺高峰期,執行緒池已滿,服務降級...";
}
(2)如果瀏覽器快速訪問4次,可能并不會看到效果,我這里采用Apache JMeter來進行并發測驗,設定了4個執行緒同時進行訪問,結果到了第4個就服務限流了

第四章 Hystrix服務監控
4.1、監控概述
Hystrix 儀表盤(Hystrix Dashboard),就像汽車的儀表盤實時顯示汽車的各項資料一樣,Hystrix 儀表盤主要用來監控 Hystrix 的實時運行狀態,通過它我們可以看到 Hystrix 的各項指標資訊,從而快速發現系統中存在的問題進而解決它,要使用 Hystrix 儀表盤功能,我們首先需要有一個Hystrix Dashboard專案,這個功能我們可以在原來的消費者應用上添加,讓原來的消費者應用具備 Hystrix 儀表盤功能,但一般地,微服務架構思想是推崇服務的拆分,Hystrix Dashboard 也是一個服務,所以通常會單獨創建一個新的工程專門用做Hystrix Dashboard服務,
4.2、工程搭建
(1)創建一個新的子工程,名字叫hystrix-dashboard6001
(2)匯入工程所需要的依賴
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
</dependencies>
(3)創建一個啟動類,并打開Hystrix的面板
com.caochenlei.HystrixDashboard6001Application
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboard6001Application {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboard6001Application.class);
}
}
(4)撰寫組態檔application.yaml
server:
port: 6001
hystrix:
dashboard:
proxy-stream-allow-list: "*"
(5)我們找到你要監控的服務,這里我們需要配置service-consumer9002的啟動類ServiceConsumer9002Application
@SpringBootApplication
@EnableFeignClients
@EnableHystrix
public class ServiceConsumer9002Application {
public static void main(String[] args) {
SpringApplication.run(ServiceConsumer9002Application.class);
}
@Bean
public ServletRegistrationBean getServlet(){
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
}
(6)重新啟動service-consumer9002和hystrix-dashboard6001
(7)我們先訪問以一下業務看看是不是正常(這一步必須做):http://localhost:9002/consumer/product/findByPid?pid=0
(8)把需要監控的地址http://localhost:9002/hystrix.stream填入http://localhost:6001/hystrix


4.3、圖表說明



第五章 Hystrix配置詳解




轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/255191.html
標籤:其他
