1.雪崩效應(yīng)
成都創(chuàng)新互聯(lián)公司從2013年成立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站制作、網(wǎng)站建設(shè)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元海城做網(wǎng)站,已為上家服務(wù),為海城各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18980820575
雪崩效應(yīng)
如上圖所示,假設(shè)我們有3個(gè)微服務(wù)A,B,C,A調(diào)用B,B調(diào)用C,如果C掛掉了,由于B是同步調(diào)用,不斷等待,導(dǎo)致資源耗盡,B也掛掉,接下來A也掛掉了,造成了雪崩效應(yīng)!為了防止雪崩效應(yīng),所以我們要在本篇文章中介紹Hystrix。
2.Hystrix
Hystrix
hystrix對(duì)應(yīng)的中文名字是“豪豬”,豪豬周身長(zhǎng)滿了刺,能保護(hù)自己不受天敵的傷害,代表了一種防御機(jī)制,反正這種豬我是沒吃過的,不敢吃。那么Hystrix又具備什么樣的特點(diǎn)呢:
2.1服務(wù)降級(jí)
雙11的時(shí)候我們經(jīng)??吹桨驯粩D爆了,這其實(shí)就是一種服務(wù)降級(jí)。那么Hystrix是怎么做到服務(wù)降級(jí)的呢?
2.1.1優(yōu)先核心服務(wù),非核心服務(wù)不可用或者弱可用
比如在一個(gè)系統(tǒng)中我們可能有限保證訂單和支付服務(wù),但是對(duì)于廣告之類的服務(wù)就若花掉
2.1.2通過HystrixCommand注解
2.1.3fallbackMethod中具體實(shí)現(xiàn)降級(jí)邏輯
2.1.4具體使用
2.1.4.1pom.xml
org.springframework.cloud spring-cloud-starter-netflix-hystrix
2.1.4.2啟動(dòng)類
//@SpringBootApplication //@EnableDiscoveryClient //@EnableCircuitBreaker @SpringCloudApplication public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); } }
在這里我們引入了@EnableCircuitBreaker這個(gè)注解,但是可以看到我們的main函數(shù)所在的類上面有好多注解了,我們這里用一個(gè)SpringCloudApplication注解包含上面的3個(gè)注解
2.1.4.3HystrixCommand與fallback的使用
@HystrixCommand(fallbackMethod="fallback") @GetMapping("/getProductInfoList") public String getProductInfoList(@RequestParam("number") Integer number) { RestTemplate restTemplate = new RestTemplate(); return restTemplate.postForObject("http://127.0.0.1:8005/product/listForOrder", Arrays.asList("157875196366160022"), String.class); } private String fallback() { return "太擁擠了, 請(qǐng)稍后再試~~"; }
假設(shè)你的方法有幾萬個(gè),上面的這種寫法用@HystrixCommand這個(gè)注解肯定要用幾萬次,太麻煩了,我們來優(yōu)化和更新一下:
@RestController @DefaultProperties(defaultFallback = "defaultFallback") public class HystrixController { @HystrixCommand(commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000") }) @GetMapping("/getProductInfoList") public String getProductInfoList(@RequestParam("number") Integer number) { RestTemplate restTemplate = new RestTemplate(); return restTemplate.postForObject("http://127.0.0.1:8005/product/listForOrder", Arrays.asList("157875196366160022"), String.class); } private String defaultFallback() { return "默認(rèn)提示:太擁擠了, 請(qǐng)稍后再試~~"; } }
直接在Controller上面寫了一個(gè)DefaultProperties這樣的注解,然后定義了一個(gè)defaultFallback這樣的方法,我們?cè)趃etProductInfoList這個(gè)方法上的@HystrixCommand注解上可以不在注明fallback方法了,因?yàn)槲覀兌加胐efaultFallback了。但是在這里我們用了一個(gè)commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000"),這個(gè)表示當(dāng)調(diào)用方法超過3秒鐘時(shí),就服務(wù)降級(jí)
2.2依賴隔離
Hystrix使用依賴隔離完成的是線程池的隔離,它為每個(gè)HystrixCommand創(chuàng)建一個(gè)單獨(dú)的線程池。這樣某個(gè)在HystrixCommand包裝下的依賴服務(wù)出現(xiàn)延遲過高的情況,也只是對(duì)該依賴的服務(wù)調(diào)用產(chǎn)生影響,并不會(huì)拖慢其他服務(wù)。使用了HystrixCommand將某個(gè)函數(shù)包裝成Hystrix命令時(shí),Hystrix框架就會(huì)自動(dòng)的為這個(gè)函數(shù)實(shí)現(xiàn)了依賴隔離,所以依賴隔離和服務(wù)降級(jí)是一體化實(shí)現(xiàn)的。
2.3服務(wù)熔斷
當(dāng)服務(wù)調(diào)用發(fā)生錯(cuò)誤到一定比例的時(shí)候,斷路器就會(huì)打開,服務(wù)的調(diào)用會(huì)轉(zhuǎn)向另外一個(gè)指定的調(diào)用方法,這就是服務(wù)熔斷,這樣說比較抽象,我們看看下面這個(gè)圖:
斷路器
斷路器一共有三個(gè)狀態(tài),初始的時(shí)候是closed狀態(tài),如果用戶不斷調(diào)用且失敗次數(shù)達(dá)到了一定的閾值,這個(gè)時(shí)候斷路器就會(huì)變成open狀態(tài),接下來用戶不斷調(diào)用這個(gè)接口都是進(jìn)入到另一個(gè)缺省方法中。但是斷路器不會(huì)一直處于open狀態(tài),當(dāng)open狀態(tài)達(dá)到一定時(shí)間后,斷路器會(huì)變成half open狀態(tài),進(jìn)入half open狀態(tài)后,將會(huì)允許請(qǐng)求再次訪問真正的服務(wù),如果訪問成功了,斷路器會(huì)變成closed狀態(tài),服務(wù)恢復(fù)正常,如果還失敗又再次進(jìn)入到open狀態(tài)。
2.3.1代碼演示
@HystrixCommand(commandProperties = { @HystrixProperty(name = "circuitBreaker.enabled", value = "true"), //設(shè)置熔斷 @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), //請(qǐng)求數(shù)達(dá)到后才計(jì)算 @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), //休眠時(shí)間窗 @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"), //錯(cuò)誤率 }) @GetMapping("/getProductInfoList") public String getProductInfoList(@RequestParam("number") Integer number) { if (number % 2 == 0) { return "success"; } RestTemplate restTemplate = new RestTemplate(); return restTemplate.postForObject("http://127.0.0.1:8005/product/listForOrder", Arrays.asList("157875196366160022"), String.class); }
通過代碼,我們可以看到,有四個(gè)參數(shù),但是最重要的還是這三個(gè)參數(shù):
1.circuitBreaker.requestVolumeThreshold 請(qǐng)求數(shù)達(dá)到后才計(jì)算
2.circuitBreaker.sleepWindowInMilliseconds open狀態(tài)達(dá)到這個(gè)時(shí)間后,就會(huì)進(jìn)入到半熔斷狀態(tài)
3.circuitBreaker.errorThresholdPercentage 失敗請(qǐng)求比例
2.3.2使用配置項(xiàng)
從上面的代碼中,我們可以看到,很多配置項(xiàng)都是寫在了代碼里面,接下來,我們把這些配置放到配置文件里面去:
@HystrixCommand @GetMapping("/getProductInfoList") public String getProductInfoList(@RequestParam("number") Integer number) { if (number % 2 == 0) { return "success"; } RestTemplate restTemplate = new RestTemplate(); return restTemplate.postForObject("http://127.0.0.1:8005/product/listForOrder", Arrays.asList("157875196366160022"), String.class); }
在yaml文件中添加這樣的配置:
hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 1000 getProductInfoList: execution: isolation: thread: timeoutInMilliseconds: 3000
在yaml文件中有一個(gè)getProductInfoList配置項(xiàng),和方法名一模一樣,還有一個(gè)default選項(xiàng),default選項(xiàng)表示所有被HystrixCommand注解的方法都可以用這個(gè)配置,getProductInfoList表示只有這個(gè)方法可以用這個(gè)配置項(xiàng)。
2.3.3feign-hystrix的使用
上面的小章節(jié)我們使用的是RestTemplate模板,接下來我們使用feign配合hystrix來進(jìn)行使用,有意思的是大家可以看看spring-cloud-starter-feign的pom.xml其實(shí)已經(jīng)在內(nèi)部依賴了hystrix。
2.3.3.1yaml配置文件
feign: hystrix: enabled: true
2.3.3.2FeignClient
@FeignClient(name = "product", fallback = ProductClient.ProductClientFallback.class) public interface ProductClient { @PostMapping("/product/listForOrder") ListlistForOrder(@RequestBody List productIdList); @PostMapping("/product/decreaseStock") void decreaseStock(@RequestBody List decreaseStockInputList); @Component static class ProductClientFallback implements ProductClient { @Override public List listForOrder(List productIdList) { return null; } @Override public void decreaseStock(List decreaseStockInputList) { } } }
兩個(gè)注意點(diǎn),一個(gè)是fallback的配置,還有一個(gè)是內(nèi)部類需要加上@Component注解
2.3.3.3調(diào)用方記得加上ComponentScan
2.4監(jiān)控HystrixDashBoard
2.4.1pom.xml
spring-cloud-starter-hystrix-dashboard
2.4.2yaml文件
management: context-path: /
2.4.3訪問
IP:PORT/hystrix
服務(wù)容錯(cuò)就講到這里,下一章節(jié)我們講解下服務(wù)跟蹤。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。