Hystrix斷路器-1
Hystrix斷路器的概述
分散式系統面臨的問題
Hystrix是什麼
Hystrix能幹啥
1. 服務降級
2. 服務熔斷
3. 接近實時的監控
Hystrix官網資料
https://github.com/Netflix/Hystrix/wiki/How-To-Use
Hystrix官宣,停更進維
Hystrix的重要概念
服務降級(fallback),服務熔斷(break),服務限流(flowlimit)
在分散式系統中,服務與服務之間依賴錯綜複雜,一種不可避免的情況就是某些服務將會出現失敗。Hystrix是一個用於處理分散式系統的延時和容錯的開源庫,它提供了服務與服務之間的容錯功能,主要體現在延遲容錯和容錯,從而做到控制分散式系統中的聯動故障。Hystrix通過隔離服務的訪問點,阻止聯動故障,並提供故障的解決方案,從而提高了這個分散式系統的彈性。
服務降級
“斷路器”本身就是一種開關裝置。當某個服務單元發生故障後,通過斷路器的故障監控(類似熔斷保險絲),向呼叫方返回一個符合預期的,可處理的備選響應(fallBack),而不是長時間的等待或者丟擲呼叫方無法處理的異常,這樣就可以保證了服務呼叫方的執行緒不會被長時間,不必要地佔用,從而避免了故障在分散式系統中的蔓延,
乃至雪崩。
哪些情況會出現降級?
l 程式執行異常
l 超時
l 服務熔斷出發服務降級
l 執行緒池/訊號量打滿也會導致服務降級
服務熔斷
類似保險絲達到最大服務訪問後,直接拒接訪問。然後呼叫服務降級的方法並返回友好提示。
就是保險絲。
服務限流
秒殺高併發等操作,嚴禁一窩峰的過來擁擠,大家排隊,一秒鐘N個,有序進行
Hystrix案例
Hystrix支付微服務構建
構建工程
1. 新建cloud-provider-hystrix-payment8001工程
2. 新增pom
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.fengyangcai.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies>
3. 寫yml
server:
port: 8001
spring:
application:
name: cloud-provider-hystrix-payment
eureka:
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://localhost:7003/eureka
#defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #叢集版本
4. 主啟動類
@SpringBootApplication @EnableEurekaClient //@EnableDiscoveryClient //@EnableCircuitBreaker//斷路器的註解 public class HystrixPaymentMain8001 { public static void main(String[] args) { SpringApplication.run(HystrixPaymentMain8001.class,args); } }
5. 業務類
Service層
@Service public class PaymentService { //正常的訪問方法 public String paymentInfo_OK(Integer id){ return "執行緒池:"+Thread.currentThread().getName()+"paymentInfo_OK,id: "+id+"/t"+"哈哈"; } //一般Hstrix降級放在客戶端,這裡放在服務端了只是演示而已。 /* @HystrixCommand(fallbackMethod = "payment_TimeOutHandler",commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000") })*/ public String paymentInfo_TimeOut(Integer id){ int time=1; // int a=10/0; try { TimeUnit.SECONDS.sleep(time); }catch (InterruptedException e){ e.printStackTrace(); } return "執行緒池:"+Thread.currentThread().getName()+"--paymentInfo_TimeOut,id: "+id+"/t"+"哈哈耗時:"+time+"秒"; } public String payment_TimeOutHandler(Integer id){ return "執行緒池:"+Thread.currentThread().getName()+"--paymentInfo_TimeOut,id: "+id+"/t"+"####系統繁忙嗚嗚嗚##"; } }
Controller層
@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"+result); return result; } @GetMapping("/payment/hystrix/timeout/{id}") public String paymentInfo_timeout(@PathVariable("id")Integer id){ String result = paymentService.paymentInfo_TimeOut(id); log.info("*******result"+result); return result; } }
6. 測試
出現情況:
Tomcat的預設的工作執行緒數被打滿了,沒有多餘的執行緒來分解壓力和處理。出現兩個都在自己轉圈圈。
上述結論
如何解決?解決的要求
建立cloud-consumer-feign-hystrix-order80消費端
Pom
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.fengyangcai.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
Yml
server:
port: 80
spring:
application:
name: cloud-consumer-feign-hystrix-order
eureka:
client:
register-with-eureka: false #表示是否將自己註冊進EurekaServer預設為true
fetch-registry: true #是否從EurekaServer捉取已有的註冊資訊,預設為true.單節點無所謂,叢集必須設定為true才能配合ribbon使用負載均衡
service-url:
#defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka
defaultZone: http://localhost:7003/eureka
主函式
其中@EnableCircuitBreaker就是引入了hystrix的熔斷註解標籤
@SpringBootApplication @EnableFeignClients @EnableCircuitBreaker public class FeignHystrixOrderMain80 { public static void main(String[] args) { SpringApplication.run(FeignHystrixOrderMain80.class,args); } }
使用openFeign在service層呼叫服務
@Component @FeignClient(value = "cloud-provider-hystrix-payment") public interface PaymentFeignHystrixService { @GetMapping("/consumer/payment/hystrix/ok/{id}") public String paymentInfo_OK(@PathVariable("id")Integer id); @GetMapping("/consumer/payment/hystrix/timeout/{id}") public String paymentInfo_timeout(@PathVariable("id")Integer id); }
Controller層
其中@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")是全域性的一個處理方法標籤。
@HystrixCommand是區域性的一個處理標籤。
@RestController @Slf4j @DefaultProperties(defaultFallback = "payment_Global_FallbackMethod") public class OrderFeignHystrixController { @Resource private PaymentFeignHystrixService paymentFeignHystrixService; @GetMapping("/payment/hystrix/ok/{id}") public String paymentInfo_OK(@PathVariable("id")Integer id){ return paymentFeignHystrixService.paymentInfo_OK(id); } //一般Hstrix降級放在客戶端 @GetMapping("/payment/hystrix/timeout/{id}") /* @HystrixCommand(fallbackMethod = "payment_TimeOutHandler",commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500") })*/ @HystrixCommand public String paymentInfo_timeout(@PathVariable("id")Integer id){ return paymentFeignHystrixService.paymentInfo_timeout(id); } public String payment_TimeOutHandler(Integer id){ return "我是消費方80.對方支付系統繁忙請稍後訪問"; } //全域性fallback方法 public String payment_Global_FallbackMethod(){ return "全域性的降級處理方法"; } }