文章知识 均来自以下系列文章,请参考原文
Spring Cloud构建微服务架构:服务容错保护(Hystrix服务降级)【Dalston版】
服务容错保护:在微服务架构中,我们将系统拆分成了一个个的服务单元,各单元应用间通过服务注册与订阅的方式互相依赖。
由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行。
这样就有可能因为网络原因或是依赖服务自身问题出现调用故障或延迟,而这些问题会直接导致调用方的对外服务也出现延迟,若此时调用方的请求不断增加,最后就会出现因 等待 出现故障的依赖方响应 而形成任务积压,线程资源无法释放,最终导致自身服务的瘫痪,甚至出现故障的蔓延 最终导致整个系统的瘫痪。
如果这样的架构存在如此严重的隐患,那么相较传统架构就更加的不稳定。为了解决这样的问题,因此产生了断路器等一系列的服务保护机制。
提供微服务架构容错能力的框架:Netflix的开源框架 Hystrix:目标在于通过控制 那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具备了服务降级、服务熔断、线程隔离、请求缓存、请求合并以及服务监控等强大功能。
Spring Cloud Hystrix:基于Netflix的开源框架 Hystrix实现,实现了线程隔离、断路器等一系列的服务保护功能。
Spring Cloud Hystrix实现断路器
step1:创建Spring Boot项目eureka-consumer-ribbon-hystrix,添加起步依赖spring-cloud-starter-netflix-eureka-server,spring-cloud-starter-netflix-ribbon,spring-cloud-starter-netflix-hystrix
step2:在项目入口添加 @EnableDiscoveryClient 注解,将当前应用加入到服务治理体系中。在项目入口添加 @EnableHystrix或者@EnableCircuitBreaker注解,开启Hystrix的使用
或者在项目入口 使用@SpringCloudApplication注解。它可以代替 @SpringBootApplication @EnableDiscoveryClient,@EnableCircuitBreaker这3个注解。这也说明Spring Cloud项目肯定是Spring Boot项目,而且Spring Cloud标准应用 应该包含服务发现以及断路器。
Step3:在application.properties文件添加配置
#微服务的名称:后续在调用的时候只需要使用该名称就可以进行服务的访问
spring.application.name=eureka-consumer-ribbon-hystrix
#微服务端口
server.port=2401
#指定服务注册中心的位置
eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
Step4:在配置类 配置ribbon 。通过ribbon 实现服务调用
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
Step5:定义 服务调用service
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
@Service
public class EurekaClientService {
@Autowired
private RestTemplate restTemplate;
//在为具体执行逻辑的函数上增加@HystrixCommand注解来指定服务降级方法,比如
@HystrixCommand(fallbackMethod = "fallback")
public String comsumer() {
String services = restTemplate.getForObject("http://eureka-client/discoveryClient", String.class);
return services;
};
//服务降级方法
public String fallback() {
System.out.println("aho this is fallback");
return "aho this is fallback";
}
}
Step6:定义controller,调用 微服务调用service
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DiscoveryClientController {
@Autowired
private EurekaClientService eurekaClientService;
@GetMapping("/consumer")
public String consumer() {
String services = eurekaClientService.comsumer();
return services;
}
}
Step7:启动eureka-server,eureka-client,eureka-consumer-ribbon-hystrix。并访问http://localhost:2401/consumer 。就会看到eureka-consumer-ribbon-hystrix 服务是如何正常消费eureka-client服务的/discoveryClient接口的
Step8:触发服务降级逻辑,将服务提供者eureka-client
的逻辑加一些延迟,比如:睡眠5秒
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DcController {
@Autowired
DiscoveryClient discoveryClient;
@GetMapping("/discoveryClient")
public String dc() throws InterruptedException {
Thread.sleep(5000L);
String services = "Services: " + discoveryClient.getServices();
System.out.println("this is eureka-client: " + services);
return services;
}
}
Step9:重启eureka-client服务,再次访问http://localhost:2401/consumer。就会看到返回 aho this is fallback
Step10:总结:
我们从eureka-client的控制台中,可以看到服务提供方输出了原本要返回的结果,但是由于返回前延迟了5秒,而服务消费方触发了服务请求超时异常,服务消费者就通过HystrixCommand注解中指定的降级逻辑进行执行,因此该请求的结果返回了fallback。
这样的机制,对自身服务起到了基础的保护,同时还为异常情况提供了自动的服务降级切换机制。