Spring Cloud【Finchley】-08使用Hystrix实现容错

简介: Spring Cloud【Finchley】-08使用Hystrix实现容错

20190806093230928.jpg


概述


前面的几篇博文,我们接触到了Eureka实现服务的注册于发现Ribbon实现客户端负载均衡Feign实现声明式的API调用,谈到微服务,容错也是不得不提的话题之一。

Soring Cloud 集成了Hystrix来提供容错的能力,从而实现微服务的容错。


实现容错主要方式


假设服务提供者的响应很慢,那么消费者的请求将会被强制等待,直到响应或者超时。 在高负载的情况下,很有可能发生的情况是,当依赖的服务不可用,自身的服务也被拖垮,这就是雪崩效应,当服务提供者不可用导致消费者不可用,并将不可用逐渐放大的过程。


容错的主要手段:


为网络请求设置超时: 通常情况下一次远程调用对应一个线程,如果响应太慢,这个线程就得不到释放,而线程占用的资源当然也不会被释放,当高并发或者未处理完的线程越来越多,资源终将被耗尽。


使用断路器模式:如果有对某个微服务的请求存在大量超时,禁止访问该微服务,防止雪崩。 当该微服务可用,断路器可以自动诊断是否已经恢复,恢复访问请求,从而实现微服务的自我修复


从而提升应用的高可用性。


Hystrix简介


https://github.com/netflix/hystrix


Hystrix是一个实现了超时机制和断路器模式的工具类库, 是由Netfix开源的一个延迟和容错库,用于隔离访问远程系统、服务或者第三方库,防止级联失败,从而提升系统可用性与容错性。


机制:


当Hystrix Command请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open).这时所有请求会直接失败而不会发送到后端服务.


断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN). 这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN).


Hystrix的断路器就像我们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量,并且断路器有自我检测并恢复的能力.


20181216190048832.png

Hystrix主要通过以下几点实现延迟和容错:


包裹请求:使用HystrixCommand / HystrixObservableCommand包裹对依赖的调用逻辑,每个命令在独立线程中执行。

跳闸机制:当某服务的错误率超过一定阀值时,Hystrix可以自动或者手动跳闸,停止请求该服务一段时间。

资源隔离:Hystrix为每个依赖都维护了一个小型的线程池(或者信号量)。如果该线程池已满,发往该依赖的请求就被立即拒绝,而不是排队等候,从而加速失败判断

监控:Hystrix可以近乎实时地监控运行指标和配置的变化,例如成功、失败、超时、以及被拒绝的请求等。

回退机制:相当于服务降级,当请求失败、超时、被拒绝,或当断路器打开时,执行回退逻辑。回退逻辑可由开发人员自行提供,例如返回一个缺省值。

自我修复:断路器打开一段时间后,会自动进入“半开”状态。


通用方式整合Hystrix


Spring Cloud官方指导:https://cloud.spring.io/spring-cloud-static/Finchley.SR2/single/spring-cloud.html#_circuit_breaker_hystrix_clients

20181216193553615.png20181216193610109.png


Step1 新建子module


因为熔断是发生在调用方即消费者,所以我们copy个消费者的工程


父工程microservice-spring-cloud右键新建Maven Module 命名为:micorservice-consumer-movie-ribbon-hystrix ,为了简单我们把micorservice-consumer-movie-ribbon的内容copy到该子模块,修改下application.yml中的spring.application.name即可。


Step2 pom增加spring-cloud-starter-netflix-hystrix依赖


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


Step3 启动类增加@EnableCircuitBreaker或者@EnableHystrix注解

package com.artisan.micorservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableCircuitBreaker
public class MicorserviceMovieRibbonHystrix {
  @Bean
  @LoadBalanced
  public RestTemplate restTemplate(){
    return new RestTemplate();
  }
  public static void main(String[] args) {
    SpringApplication.run(MicorserviceMovieRibbonHystrix.class, args);
  }
}


Step4 控制层增加注解即容错方法

package com.artisan.micorservice.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
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;
import com.artisan.micorservice.model.User;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import lombok.extern.slf4j.Slf4j;
@RestController
public class MovieController {
  @Autowired
  private RestTemplate restTemplate;
  @Autowired
  LoadBalancerClient loadBalancerClient;
  @HystrixCommand(fallbackMethod = "findByIdDefault")
  @GetMapping("/movie/{id}")
  public User findById(@PathVariable Long id) {
    return this.restTemplate.getForObject("http://microservice-provider-user/user/" + id, User.class);
  }
  /**
   * 
   * @param id
   * @return
   * @desc 当请求失败、超时、被拒绝,或当断路器打开时,执行的逻辑
   */
  public User findByIdDefault(Long id) {
    User user = new User();
    user.setId(id);
    user.setUsername("默认用户");
   return user;
  }
}


从上述Controller层的方法中,可以看到我们在findById方法上增加了注解 @HystrixCommand(fallbackMethod = “findByIdDefault”),并通过fallbackMethod 属性指定了当请求失败、超时、被拒绝,或当断路器打开时,执行的方法findByIdDefault.


20181216194521133.png

HystrixCommand注解还可以使用注解HystrixProperty的commandProperties属性来配置HystrixCommand

比如

 @HystrixCommand(fallbackMethod = "findByIdDefault",commandProperties= {
      @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000"),
      @HystrixProperty(name="metrics.rollingStats.timeInMilliseconds",value="10000")
  },threadPoolProperties= {
      @HystrixProperty(name="coreSize",value="1"),
      @HystrixProperty(name="maxQueueSize",value="10")
  })
  @GetMapping("/movie/{id}")
  public User findById(@PathVariable Long id) {
    return this.restTemplate.getForObject("http://microservice-provider-user/user/" + id, User.class);
  }


可配置的属性见官网: https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica#configuration


Step5 测试


启动microservice-discovery-eureka,注册中心

启动micorservice-provider-user,服务提供者

启动micorservice-consumer-movie-ribbon-hystrix,服务消费者,整合了Hystrix

访问http://localhost:8761/ 确认下服务已经注册成功。


20181216200130352.png


访问: http://localhost:7902/movie/2 ,返回

{"id":2,"username":"artisan2","name":"小工匠二","age":20,"balance":200.00}


停止 micorservice-provider-user,服务提供者 ,注册中心上已经没有该服务了。


20181216200315697.png


访问http://localhost:7902/movie/2 ,可访问多次,均返回

{"id":2,"username":"默认用户","name":null,"age":null,"balance":null}


已经走到了我们自定义的方法中。

再次启动 micorservice-provider-user,服务提供者


20181216200448647.png

访问http://localhost:7902/movie/2

{"id":2,"username":"artisan2","name":"小工匠二","age":20,"balance":200.00}


服务已经恢复。

当请求失败、被拒绝、超时或者断路器打开时都会进入到回退的方法,当进入回退方法并不意味着断路器已经被打开。


代码


https://github.com/yangshangwei/SpringCloudMaster/tree/master/micorservice-consumer-movie-ribbon-hystrix

相关实践学习
部署高可用架构
本场景主要介绍如何使用云服务器ECS、负载均衡SLB、云数据库RDS和数据传输服务产品来部署多可用区高可用架构。
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
30天前
|
负载均衡 Java API
Spring Cloud 面试题及答案整理,最新面试题
Spring Cloud 面试题及答案整理,最新面试题
132 1
|
30天前
|
Java Nacos Sentinel
Spring Cloud Alibaba 面试题及答案整理,最新面试题
Spring Cloud Alibaba 面试题及答案整理,最新面试题
139 0
|
1月前
|
SpringCloudAlibaba Java 持续交付
【构建一套Spring Cloud项目的大概步骤】&【Springcloud Alibaba微服务分布式架构学习资料】
【构建一套Spring Cloud项目的大概步骤】&【Springcloud Alibaba微服务分布式架构学习资料】
131 0
|
3天前
|
负载均衡 Java 开发者
细解微服务架构实践:如何使用Spring Cloud进行Java微服务治理
【4月更文挑战第17天】Spring Cloud是Java微服务治理的首选框架,整合了Eureka(服务发现)、Ribbon(客户端负载均衡)、Hystrix(熔断器)、Zuul(API网关)和Config Server(配置中心)。通过Eureka实现服务注册与发现,Ribbon提供负载均衡,Hystrix实现熔断保护,Zuul作为API网关,Config Server集中管理配置。理解并运用Spring Cloud进行微服务治理是现代Java开发者的关键技能。
|
3天前
|
Java API 对象存储
对象存储OSS产品常见问题之使用Spring Cloud Alibaba情况下文档添加水印如何解决
对象存储OSS是基于互联网的数据存储服务模式,让用户可以安全、可靠地存储大量非结构化数据,如图片、音频、视频、文档等任意类型文件,并通过简单的基于HTTP/HTTPS协议的RESTful API接口进行访问和管理。本帖梳理了用户在实际使用中可能遇到的各种常见问题,涵盖了基础操作、性能优化、安全设置、费用管理、数据备份与恢复、跨区域同步、API接口调用等多个方面。
22 2
|
18天前
|
负载均衡 网络协议 Java
构建高效可扩展的微服务架构:利用Spring Cloud实现服务发现与负载均衡
本文将探讨如何利用Spring Cloud技术实现微服务架构中的服务发现与负载均衡,通过注册中心来管理服务的注册与发现,并通过负载均衡策略实现请求的分发,从而构建高效可扩展的微服务系统。
|
18天前
|
开发框架 负载均衡 Java
Spring boot与Spring cloud之间的关系
总之,Spring Boot和Spring Cloud之间的关系是一种构建和扩展的关系,Spring Boot提供了基础,而Spring Cloud在此基础上提供了分布式系统和微服务架构所需的扩展和工具。
16 4
Spring boot与Spring cloud之间的关系
|
19天前
Springcloud-ribbon和hystrix配置
Springcloud-ribbon和hystrix配置
7 0
|
5月前
|
缓存 运维 监控
微服务技术系列教程(22) - SpringCloud- 服务保护机制Hystrix
微服务技术系列教程(22) - SpringCloud- 服务保护机制Hystrix
60 0
|
6月前
|
缓存 监控 Java
12SpringCloud - 断路器(Hystrix)引入
12SpringCloud - 断路器(Hystrix)引入
28 0