SpringCloud之Hystrix的詳細(xì)使用
1.概念
服務(wù)降級(jí):服務(wù)器繁忙,請(qǐng)稍后再試,不讓客戶端等待,并立即返回一個(gè)友好的提示(一般發(fā)生在 程序異常,超時(shí),服務(wù)熔斷觸發(fā)服務(wù)降級(jí),線程池、信號(hào)量 打滿也會(huì)導(dǎo)致服務(wù)降級(jí))
服務(wù)熔斷 : 達(dá)到最大服務(wù)訪問后,直接拒絕訪問,然后調(diào)用服務(wù)降級(jí)的方法并返回友好提示(如保險(xiǎn)絲一樣)
服務(wù)限流 : 秒殺等高并發(fā)操作,嚴(yán)禁一窩蜂的過來擁擠,排隊(duì)進(jìn)入,一秒鐘N個(gè),有序進(jìn)行
***一.服務(wù)降級(jí)***
2.不使用Hystrix的項(xiàng)目
大致的Service和Controller層如下
***************Controller***************** package com.sky.springcloud.controller; import com.sky.springcloud.service.PaymentService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; @RestController @Slf4j public class PaymentController { @Resource private PaymentService paymentService; @Value("${server.port}") private String serverport; @GetMapping("/payment/hystrix/ok/{id}") public String paymentInfo_Ok(@PathVariable("id") Integer id){ String result = paymentService.paymentInfo_ok(id); log.info("*****"+ result); return result; } @GetMapping("/payment/hystrix/timeout/{id}") public String paymentInfo_TimeOut(@PathVariable("id") Integer id){ String result = paymentService.payment_Info_TimeOut(id); } *******************Service******************** package com.sky.springcloud.service; import org.springframework.stereotype.Service; import java.util.concurrent.TimeUnit; @Service public class PaymentServiceImpl implements PaymentService{ @Override public String paymentInfo_ok(Integer id) { return "線程池:" + Thread.currentThread().getName() + "paymentInfo_Ok. id:" + id + "\t" + "~~~~~"; public String payment_Info_TimeOut(Integer id) { try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } return "線程池:" + Thread.currentThread().getName() + "paymentInfo_TimeOut. id:" + id + "\t" + "~~~~~";
在這種情況時(shí),當(dāng)通過瀏覽器訪問 TimeOut這個(gè)方法,會(huì)三秒后返回結(jié)果,而當(dāng)訪問 OK 這個(gè)方法時(shí),會(huì)直接返回結(jié)果(但是這是在訪問量很少的時(shí)候,一旦訪問量過多,訪問OK時(shí)也會(huì)出現(xiàn)延遲,這里可以使用Jmeter模擬兩萬個(gè)訪問量,如下)
使用 Jmeter 模擬后,再去訪問OK,會(huì)明顯出現(xiàn)加載的效果
3. 使用Hystrix
在主啟動(dòng)類添加注解
@EnableHystrix
package com.sky.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.hystrix.EnableHystrix; @SpringBootApplication @EnableEurekaClient //啟用Eureka @EnableHystrix //啟用Hystrix public class Payment8001 { public static void main(String[] args) { SpringApplication.run(Payment8001.class,args); } }
在原有的基礎(chǔ)上,在Service層加上如下注解
@HystrixCommand(fallbackMethod = "payment_Info_TimeOutHandler",//當(dāng)服務(wù)降級(jí)時(shí),調(diào)用payment_Info_TimeOutHandler方法 commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")//設(shè)置時(shí)間為3秒,超過三秒就為時(shí)間超限
*****************改后的Service******************* package com.sky.springcloud.service; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; import org.springframework.stereotype.Service; import java.util.concurrent.TimeUnit; @Service public class PaymentServiceImpl implements PaymentService{ @Override public String paymentInfo_ok(Integer id) { return "線程池:" + Thread.currentThread().getName() + "paymentInfo_Ok. id:" + id + "\t" + "~~~~~"; } @HystrixCommand(fallbackMethod = "payment_Info_TimeOutHandler",commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000") }) public String payment_Info_TimeOut(Integer id) { try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } // int a = 10 / 0; return "線程池:" + Thread.currentThread().getName() + "paymentInfo_TimeOut. id:" + id + "\t" + "~~~~~"; } public String payment_Info_TimeOutHandler(Integer id){ return "線程超時(shí)或異常 " + Thread.currentThread().getName(); } }
如上Service所示,如果再次訪問TimeOut需要等待五秒,但是Hystrix設(shè)置的超時(shí)時(shí)間為三秒,所以當(dāng)三秒后沒有結(jié)果就會(huì)服務(wù)降級(jí),從而調(diào)用TimeOutHandler這個(gè)指定 的方法來執(zhí)行(或者有程序出錯(cuò)等情況也會(huì)服務(wù)降級(jí))
4. 全局的Hystrix配置
@DefaultProperties(defaultFallback = “Gloub_Test”)
package com.sky.springcloud.service; import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; import org.springframework.stereotype.Service; @Service @DefaultProperties(defaultFallback = "Gloub_Test") public class PaymentServiceImpl implements PaymentService{ @Override @HystrixCommand public String paymentInfo_ok(Integer id) { int a = 10 / 0; return "線程池:" + Thread.currentThread().getName() + "paymentInfo_Ok. id:" + id + "\t" + "~~~~~"; } @HystrixCommand(fallbackMethod = "payment_Info_TimeOutHandler",commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000") }) public String payment_Info_TimeOut(Integer id) { /* try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }*/ return "線程池:" + Thread.currentThread().getName() + "paymentInfo_TimeOut. id:" + id + "\t" + "~~~~~"; public String payment_Info_TimeOutHandler(Integer id){ return "線程超時(shí)或異常 " + Thread.currentThread().getName(); public String Gloub_Test(){ return "走了全局的"; }
如上Service所示,加了@HystrixCommand的方法里,
如果沒指定fallbackMethod 就會(huì)默認(rèn)去找全局的defaultFallback
這里 當(dāng)paymentInfo_ok 方法出錯(cuò)時(shí),會(huì)調(diào)用Gloub_Test方法
當(dāng)payment_Info_TimeOut出錯(cuò)時(shí),會(huì)調(diào)用payment_Info_TimeOutHandler方法
***二.服務(wù)熔斷***
1.熔斷機(jī)制概述
熔斷機(jī)制是應(yīng)對(duì)雪崩效應(yīng)的一種微服務(wù)鏈路保護(hù)機(jī)制,當(dāng)扇出鏈路的某個(gè)微服務(wù)出錯(cuò)不可用或者響應(yīng)時(shí)間太長,會(huì)進(jìn)行服務(wù)的降級(jí),進(jìn)而熔斷該節(jié)點(diǎn)微服務(wù)的調(diào)用,快速返回錯(cuò)誤的相應(yīng)信息.當(dāng)檢測(cè)到該節(jié)點(diǎn)微服務(wù)調(diào)用相應(yīng)正常后,恢復(fù)調(diào)用鏈路.
2.項(xiàng)目中使用
在上面的基礎(chǔ)上,改寫Service和Controller(添加以下代碼)
//是否開啟服務(wù)熔斷(斷路器) @HystrixProperty(name = "circuitBreaker.enabled",value = "true"), //服務(wù)請(qǐng)求的次數(shù) @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"), //時(shí)間的窗口期 @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), //當(dāng)失敗率達(dá)到多少后發(fā)生熔斷 @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"), ******************Service***************** @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback", commandProperties = { @HystrixProperty(name = "circuitBreaker.enabled",value = "true"), @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"), @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"), }) public String PaymentCircuitBreaker(@PathVariable("id") Integer id){ if(id<0){ throw new RuntimeException("********** id不能為負(fù)"); } String serialNumber = IdUtil.simpleUUID(); return Thread.currentThread().getName() + "\t" + serialNumber; } public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id){ return "id 不能為負(fù):" + id; ************Controller******************** @GetMapping("/payment/circuit/{id}") String result = paymentService.PaymentCircuitBreaker(id); log.info(result + "***********"); return result;
如上所示,當(dāng)訪問paymentCircuitBreaker時(shí),如果id小于零則會(huì)有一個(gè)運(yùn)行錯(cuò)誤,這時(shí)候就會(huì)通過服務(wù)降級(jí)來調(diào)用paymentCircuitBreaker_fallback方法,當(dāng)錯(cuò)誤的次數(shù)達(dá)到60%的時(shí)候(自己設(shè)的),就會(huì)出現(xiàn)服務(wù)熔斷,這個(gè)時(shí)候再訪問id大于零的情況,也會(huì)發(fā)生服務(wù)降級(jí),因?yàn)殚_起了服務(wù)熔斷,需要慢慢的恢復(fù)正常.
到此這篇關(guān)于SpringCloud之Hystrix的詳細(xì)使用的文章就介紹到這了,更多相關(guān)SpringCloud Hystrix使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java 延遲隊(duì)列的常用的實(shí)現(xiàn)方式
這篇文章主要介紹了Java 延遲隊(duì)列的常用的實(shí)現(xiàn)方式,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下2021-04-04Spring?Boot+Vue實(shí)現(xiàn)Socket通知推送的完整步驟
最近工作中涉及消息通知功能的開發(fā),所以下面這篇文章主要給大家介紹了關(guān)于Spring?Boot+Vue實(shí)現(xiàn)Socket通知推送的完整步驟,文中通過實(shí)例代碼以及圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04spring cloud如何修復(fù)zuul跨域配置異常的問題
最近的開發(fā)過程中,使用spring集成了spring-cloud-zuul,在配置zuul跨域的時(shí)候遇到了問題,下面這篇文章主要給大家介紹了關(guān)于spring cloud如何修復(fù)zuul跨域配置異常的問題,需要的朋友可以參考借鑒,下面來一起看看吧。2017-09-09Java基礎(chǔ)之詳細(xì)總結(jié)五種常用運(yùn)算符
在通常代碼邏輯處理中,我們常常都會(huì)使用到運(yùn)算符,今天我們就詳細(xì)了解一下運(yùn)算符的使用以及分類.運(yùn)算符是對(duì)常量或者變量進(jìn)行操作的符號(hào),它分為算術(shù)運(yùn)算符,賦值運(yùn)算符,比較運(yùn)算符,邏輯運(yùn)算符以及位運(yùn)算符.需要的朋友可以參考下2021-05-05Java與SpringBoot對(duì)redis的使用方式
這篇文章主要介紹了Java與SpringBoot對(duì)redis的使用方式,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-08-08JavaSE面試題之this與super關(guān)鍵字的區(qū)別詳解
this關(guān)鍵字用于引用當(dāng)前對(duì)象的引用,super關(guān)鍵字用于引用父類對(duì)象的引用,下面這篇文章主要給大家介紹了關(guān)于JavaSE面試題之this與super關(guān)鍵字區(qū)別的相關(guān)資料,需要的朋友可以參考下2023-12-12