在微服务架构中,我们将系统拆分成了一个个的服务单元,各单元应用间通过服务注册与订阅的方式互相依赖。由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身问题出现调用故障或延迟,而这些问题会直接导致调用方的对外服务也出现延迟,若此时调用方的请求不断增加,最后就会出现因等待出现故障的依赖方响应而形成任务积压,线程资源无法释放,最终导致自身服务的瘫痪,进一步甚至出现故障的蔓延最终导致整个系统的瘫痪。如果这样的架构存在如此严重的隐患,那么相较传统架构就更加的不稳定。为了解决这样的问题,因此产生了断路器等一系列的服务保护机制。
在Spring Cloud Hystrix中实现了线程隔离、断路器等一系列的服务保护功能。
依然在eureka-server
工程 和 eureka-client
工程 基础上。
创建一个服务消费者 eureka-consumer-ribbon-hystrix
1、pom.xml
的dependencies节点中引入spring-cloud-starter-hystrix
依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</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.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
application.properties 配置
spring.application.name=eureka-consumer-ribbon-hystrix
server.port=12101
eureka.client.serviceUrl.defaultZone=http://localhost:11001/eureka/
2、 在应用主类中使用@EnableCircuitBreaker
或@EnableHystrix
注解开启Hystrix的使用:
@EnableCircuitBreaker
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaConsumerRibbonHystrixApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaConsumerRibbonHystrixApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
3、改造服务消费方式,新增ConsumerService
类,然后将在Controller
中的逻辑迁移过去。最后,在为具体执行逻辑的函数上增加 @HystrixCommand
注解来指定服务降级方法,比如:
@Service
public class ConsumerService {
@Autowired
RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "fallback")
public String consumer() {
return restTemplate.getForObject("http://eureka-client/hello", String.class);
}
public String fallback() {
return "fallback";
}
}
@RestController
public class HelloController {
@Autowired
ConsumerService consumerService;
@GetMapping("/consumer")
public String hello() {
System.out.println("eureka-consumer-ribbon");
return consumerService.consumer();
}
}
下面我们来验证一下上面Hystrix带来的一些基础功能。我们先把涉及的服务都启动起来,然后访问
http://localhost:12101/consumer
为了触发服务降级逻辑,我们可以将服务提供者eureka-client
的逻辑加一些延迟,比如
@RestController
public class HelloController {
@Autowired
DiscoveryClient discoveryClient;
@GetMapping("/hello")
public String hello() throws InterruptedException {
//为触发降级,逻辑做一些延迟
Thread.sleep(6000L);
String services = "Services: " + discoveryClient.getServices();
System.out.println(services);
return services;
}
}
重启eureka-client
之后,再尝试访问localhost:2101/consumer
,此时我们将获得的返回结果为:fallback