一.雪崩效应
(1)微服务架构的系统通常包含多个服务层,每一个服务专注于自己的业务逻辑,并对外提供相应的接口,各服务间通过服务注册与订阅的方式互相依赖。假如有一个请求需要调用A服务,但A服务出现了问题,则这个请求就会阻塞,那么只要调用服务A的请求都会阻塞,当阻塞的请求越来越多,占用的计算机资源就越来越多。当一个服务出现问题,可能导致所有的请求都不可用,从而导致整个分布式系统都不可用,这就是“雪崩效应”。
(2)雪崩效应产生的原因:
硬件故障:比如服务器主机死机,机房断电等。
流量激增:比如异常流量、用户重试导致系统负载升高。
缓存刷新:假设A为client端,B为Server端,假设A系统请求都流向B系统,请求超出了B系统的承载能力,就会造成B系统崩溃。
程序有Bug:代码循环调用的逻辑问题,资源未释放引起的内存泄漏等问题;
二.服务熔断和服务降级
(1)服务熔断
当对于目标服务的请求和调用大量超时或失败时,应该熔断该服务的所有调用,并且对于后续调用应直接返回,从而快速释放资源,确保在目标服务不可用的这段时间内,所有对它的调用都是立即返回,不会阻塞的。在SpringCloud框架里,熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败,就会启动熔断机制。
(2)服务降级
服务降级一般从整体负荷考虑,当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级。服务将不再被调用,这时客户端可以自己准备一个本地的fallback回调返回一个缺省值。从而释放服务器资源以保证核心业务正常运作或高效运作。
三.使用SpringCloud Hystrix实现服务容错
(1)在pom.xml中添加以下依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
(2)在启动类上添加@EnableCircuitBreaker或@EnableHystrix注解。
package com.example.hystrixdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableCircuitBreaker
@EnableDiscoveryClient
public class HystrixDemoApplication {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(HystrixDemoApplication.class, args);
}
}
(3)CompanyController控制器代码。
package com.example.hystrixdemo.controller;
import com.example.hystrixdemo.entity.User;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class CompanyController {
@Autowired
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "getByIdFallback",commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),
@HystrixProperty(name = "metrics.rollingStats.thread.timeInMilliseconds", value = "5000")
}, threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "1")
})
@GetMapping("/user/{id}")
public User getById(@PathVariable Integer id){
return restTemplate.getForObject("http://localhost:8001/"+id,User.class);
}
public User getByIdFallback(@PathVariable Integer id){
User user=new User();
user.setId(0);
user.setName("默认员工");
return user;
}
}