前言
前两篇文章中,我们分别展示了如何用Eureka结合ribbon和feign来做服务消费的过程,并且证明了两个组件都有负载均衡的功能,然而,由于只是简单介绍,所以采用的例子比较简单,服务的数量也只有几个,所以,其实很多隐藏的问题我们没有重现,但并不意味着不存在。
在真正的微服务架构中,服务之间的调用关系错综复杂,一个服务可能调用很多个服务或者被很多服务调用,如果这个服务因为网络原因或自身问题出现调用故障或延迟,会导致调用方的对外服务也出现延迟,调用方的请求被阻塞,从而影响到其他调用的服务,一个阻塞,两个阻塞…像滚雪球一样导致整个系统的线程资源被严重占用,最后奔溃,这就是常说的“雪崩”现象。
一、断路器Hystrix
上述的问题在微服务系统中非常常见的,为了有效防止这种情况的发生,Netflix开源了Hystrix组件,实现了断路器模式,而SpringCloud对这一组件进行了整合。
Hystrix具备了服务降级、服务熔断、线程隔离、请求缓存、请求合并以及服务监控等强大功能。
正常来说,一般的服务访问是这样的:
假设其中一个服务故障后,服务A对其调用失败,达到一个阈值后,hystrix会开启断路器模式,直接返回一个fallbackMethod方法,方法里面可以自定义处理,从而达到服务降级的作用,如图所示:
二、hystrix结合ribbon工程
这里的例子是基于之前文章的工程,读者可以参考《springcloud微服务系列教程(四) 服务消费者 Spring Cloud Feign》
改造eureka-ribbon工程代码,首先在pom文件中加入hystrix的依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
在程序的启动类加上注解@EnableHystrix,开启Hystrix的功能:
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
public class EurekaApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
然后,改造controller类,在"/consumer"接口上加入注解@HystrixCommand
@RestController
public class ConsumeController {
@Autowired
private LoadBalancerClient client;
@Autowired
RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "consumerError")
@GetMapping("/consumer")
public String consumer() {
String dc = restTemplate.getForObject("http://eureka-client/hello",String.class);
return dc;
}
public String consumerError(){
return "consumer error!";
}
}
fallbackMethod返回的是一个名为 “consumerError” 的方法,当断路器启动后会返回这个方法。直接输出 “consumer error!” 。
先后启动eureka-server和eureka-client两个工程,然后再启动ribbon的工程,
访问http://localhost:1111/,可以看到服务已经注册成功!
然后,在浏览器中访问http://localhost:1114/consumer,可以看到浏览器成功输出
hello : 1112
说明ribbon服务成功调用eureka-client的接口并返回信息,把eureka-client服务关闭,刷新页面,我们看到浏览器输出
consumer error!
说明fallbackMethod的方法成功返回,断路器起到了作用。
三、改造feign工程
刚才的例子证明了hystrix可以结合ribbon来实现断路器功能,接下来我们换成feign工程,看能否成功。
feign的工程也是引用之前文章的例子,不明白的读者可以看。。。。。。。
启动eureka-server和eureka-client工程,打开feign-client的配置文件bootstrap.yml,加入下面的配置信息:
feign:
hystrix:
enabled: true
因为feign是自带断路器的,但在新版本中,断路器默认没有打开,需要加上上面的配置。
完成之后,在 FeignService 接口上加入falback的指定类,这是feign调用断路器的用法:
@FeignClient(value = "eureka-client",fallback = FeignHystrixService.class)
public interface FeignService {
@GetMapping("/hello")
String helloCallBack();
}
FeignHystrixService 需要实现 FeignService 接口,在方法中定义降级后的操作:
@Service
public class FeignHystrixService implements FeignService{
@Override
public String helloCallBack() {
return "service error!";
}
}
开启工程,在浏览器访问http://localhost:1119/feignhello,输出信息如下:
hello : 1112
断开eureka-client,再次访问,可以看到浏览器输出:
service error!
至此,我们成功实现了feign断路器的例子。
本文源码地址:https://github.com/Taoxj/SpringCloudDemo/tree/master/hystrix