zl程序教程

您现在的位置是:首页 >  后端

当前栏目

[SpringCloud系列010] SpringCloud之Hystrix

SpringCloud 系列 Hystrix 010
2023-09-27 14:29:28 时间

Hystrix 介绍 详解,服务降级,熔断,限流
这里写图片描述
服务雪崩效应–级联效应
**服务雪崩效应:**因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过 程,就叫服务雪崩效应
导致雪崩效应的最根本原因是: 大量请求线程同步等待造成的资源耗尽

解决方案

  1. 超时机制
  2. 服务限流
  3. 服务熔断
  4. 服务降级

在整个SpringCloud构建微服务的体系中,有一个提供超时机制,限流,熔断,降级最全面 的实现:Hystrix(豪猪) 翻译过来表示:自身带刺,有自我保护的意思,外国人起名字还是 很有意思滴。当然Hystrix并不是Spring的,而是NetFlix公司开源的。那么Spring只是把它 拿过来,在他的基础上面做了一些封装,然后加入到了SpringCloud中,实现高可用的分布 式微服务架构

引入hystrix
这里写图片描述
@HystrixCommond
@EnableCircuitBreaker

那么Hystrix是怎么做到降级的呢? 他通过一种叫做“命令模式”的方式,继承(HystrixCommand类)来包裹具体的服务调用 逻辑(run方法), 并在命令模式中添加了服务调用失败后的降级逻辑(getFallback),见 (OrderServiceCommand类)
这里写图片描述
降级(报错,超时)
fallback fallbackMethod,返回静态的信息.备用接口/缓存/mock数据

熔断fusing
重试次数,自动恢复时间,可以再yml中配置的
测试报错和正常的情况,我们可以看到当报错达到一定阈值时,会自动熔断,阈值可以配
置,如下: 一个rolling window内最小的请求数。如果设为20,那么当一个rolling window的时间内(比如说1个rolling window是10秒)收到19个请求,即使19个请求都失败,也不会触发
circuit break。默认20 hystrix.command.default.circuitBreaker.requestVolumeThreshold # 触发短路的时间值,当该值设为5000时,则当触发circuit break后的5000毫秒内都会拒 绝request,也就是5000毫秒后才会关闭circuit。默认5000 hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds

限流
配置线程组 线程池,队列 默认是10个线程

fallback的数据会统计在Metrics中,就是配置熔断的时候使用

用JMeter做压测

@HystrixCommand(fallbackMethod = “findByIdFallback”)

@RestController
public class OrderController {
  private static final Logger logger =
   LoggerFactory.getLogger(OrderController.class);
  @Autowired
  private RestTemplate restTemplate;

  @HystrixCommand(fallbackMethod = "findByIdFallback")
  @GetMapping("/user/{id}")
  public User findById(@PathVariable Long id) {
	logger.info("================请求用户中心接口==============");
    return this.restTemplate.getForObject(
    "http://microservice-provider-user/" + id, User.class);
  }

  public User findByIdFallback(Long id) { 
    User user = new User();
    user.setId(-1L);
    user.setName("默认用户");
    return user;
  }

}
@EnableDiscoveryClient
@SpringBootApplication
@EnableCircuitBreaker
public class ConsumerOrderApplication {
  @Bean
  @LoadBalanced
  public RestTemplate restTemplate() {
    return new RestTemplate();
  }

  public static void main(String[] args) {
    SpringApplication.run(ConsumerOrderApplication.class, args);
  }
}

降级配置

server:
  port: 8010
spring:
  application:
    name: microservice-consumer-order
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
hystrix:
  command:
    default:
      circuitBreaker:
        requestVolumeThreshold: 1
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 4000

UserController

@RestController
public class UserController {
	
  private final Logger logger = Logger.getLogger(getClass());
	
  @Autowired
  private UserRepository userRepository;
  @Autowired
  private Registration registration;
  

  @GetMapping("/{id}")
  public User findById(@PathVariable Long id) throws Exception {
	  logger.info("用户中心接口:查询用户"+ id +"信息");
	  /*//测试超时触发降级
	  int sleepTime = new Random().nextInt(2000);
	  logger.info("sleepTime:" + sleepTime);
	  Thread.sleep(sleepTime);  */
	  
	  /*//测试熔断,传入不存在的用户id模拟异常情况
	  if (id == 10) {
	    throw new NullPointerException();
	  }*/
	  
	  //测试限流,线程资源隔离,模拟系统执行速度很慢的情况
	 // Thread.sleep(3000);
	  
	  User findOne = userRepository.findOne(id);
	  return findOne;
  }
  
  @GetMapping("/getIpAndPort")
  public String findById() {
	  return registration.getHost() + ":" + registration.getPort();
  }
}

熔断配置

server:
  port: 8010
spring:
  application:
    name: microservice-consumer-order
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
hystrix:
  command:
    default:
      circuitBreaker:
        requestVolumeThreshold: 3 #次数
        sleepWindowInMilliseconds: 10000  #时间

限流,超时模拟

测试限流,线程资源隔离,模拟系统执行速度很慢的情况
 Thread.sleep(3000);
server:
  port: 8010
spring:
  application:
    name: microservice-consumer-order
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 20000

配置线程池线程组
参数queueSizeRejectionThreshold 和maxQueueSize 。queueSizeRejectionThreshold默认值是5,允许在队列中的等待的任务数量,超过线程组配置大小的请求直接降级,优先输出,返回结果

@RestController
public class OrderController {
	private static final Logger 
	logger=LoggerFactory.getLogger(OrderController.class);
	@Autowired
	private RestTemplate restTemplate;

	@HystrixCommand(fallbackMethod = "findByIdFallback", 
					groupKey = "orderUserGroup", 
					threadPoolKey = "orderUserIdThreadPool", 
					threadPoolProperties = {
				    @HystrixProperty(name = "coreSize", value = "2"), 
				    @HystrixProperty(name ="queueSizeRejectionThreshold",
				     value = "1") })
	@GetMapping("/user/{id}")
	public User findById(@PathVariable Long id) {
		logger.info("==============");
		"http://microservice-provider-user/" + id, User.class);	
	}
	public User findByIdFallback(Long id) {
		User user = new User();
		user.setId(-1L);
		user.setName("默认用户");
		return user;
	}
}

引入依赖

 <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>