在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以相互调用(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包
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
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