在微服務架構中,根據業務來拆分成一個個的服務,服務與服務之間可以互相調用(RPC),在Spring Cloud可以用RestTemplate+Ribbon和Feign來調用。為了保證其高可用,單個服務通常會叢集部署。由于網絡原因或者自身的原因,服務并不能保證100%可用,如果單個服務出現問題,調用這個服務就會出現線程阻塞,此時若有大量的請求湧入,Servlet容器的線程資源會被消耗完畢,導緻服務癱瘓。服務與服務之間的依賴性,故障會傳播,會對整個微服務系統造成災難性的嚴重後果,這就是服務故障的“雪崩”效應。
為了解決這個問題,業界提出了斷路器模型。Netflix提供Hystrix元件,實作了斷路器模式。
一. 斷路器(Circuit Breaker)簡介: Hystrix Clients
Netflix has created a library called Hystrix that implements the circuit breaker pattern. In a microservice architecture, it is common to have multiple layers of service calls.
A service failure in the lower level of services can cause cascading failure all the way up to the user. When calls to a particular service exceed circuitBreaker.requestVolumeThreshold (default: 20 requests) and the failure percentage is greater than circuitBreaker.errorThresholdPercentage(default: >50%) in a rolling window defined by metrics.rollingStats.timeInMilliseconds (default: 10 seconds), the circuit opens and the call is not made. In cases of error and an open circuit, a fallback can be provided by the developer.
Netflix提供Hystrix元件,實作了斷路器模式。在微服務架構中,一個請求需要調用多個服務是很常見的。一個底層的服務出現故障會導緻連鎖故障。當調用特定的服務在一個周期(預設10秒)内超過斷路器的請求門檻值(預設20次)并且失敗比超過斷路器的異常門檻值比(預設:>50%),斷路器将會被打開,此時可提供一個fallback方法傳回一個固定值。
二. 在消費端eureka_ribbon引入Hystrix
1. pom.xml引入jar包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
2. Application.java開啟斷路器
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class Application {
public static void main( String[] args ) {
new SpringApplicationBuilder(Application.class)
.web(WebApplicationType.SERVLET).run(args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
3. Service加入@HystrixCommand,配置熔斷後的預設傳回值
@Service
public class HelloService {
@Autowired
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "defaultSayHello")
public String sayHello() {
return restTemplate.getForObject("http://eurekaClient/sayHello", String.class);
}
public String defaultSayHello() {
return "Hello, so sorry";
}
}
4. 停止兩個eureka_client的服務或将健康狀态設定為DOWN,在通路消費端的對外接口,将傳回斷路器預設資料(需要多請求幾次,會存在一定延遲);當服務恢複正常,接口傳回也将正常(存在一定延遲)
三、在消費端eureka_feign使用hystrix
Feign自帶斷路器,使用feign.hystrix.enabled=true打開即可
1. application.properties
feign.hystrix.enabled=true
2. 實作接口用于fallback
@Component
public class HelloServiceFallback implements HelloService {
@Override
public String sayHello() {
return "Hello, so sorry";
}
}
3. 在接口中配置fallback
package com.kevin.eureka_feign.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(name="eurekaClient", fallback = HelloServiceFallback.class)
public interface HelloService {
@RequestMapping("/sayHello")
String sayHello();
}
4. 在服務端不能正常提供服務的情況下通路http://127.0.0.1:9202/sayHello
5. 如果需要通路導緻失敗回退觸發的原因,可以使用@FeignClient中的fallbackFactory屬性。可參考官方例子。
參考:
https://cloud.spring.io/spring-cloud-static/Greenwich.SR1/single/spring-cloud.html#_circuit_breaker_hystrix_clients
https://cloud.spring.io/spring-cloud-static/Greenwich.SR1/single/spring-cloud.html#spring-cloud-feign-hystrix