SpringCloud微服务之四:使用Hystrix实现微服务的容错限流

SpringCloud微服务之四:使用Hystrix实现微服务的容错限流


一、雪崩效应

1、雪崩效应概念

  • 1、服务雪崩效应是一种因“服务提供者的不可用”(原因)导致“服务调用者不可用”(结果),并将不可用逐渐放大的过程,称之为雪崩效应。
    在这里插入图片描述

2、雪崩效应形成原因

服务雪崩的过程可以分为三个阶段:

  • 服务提供者不可用;
  • 硬件故障
  • 程序bug
  • 缓存击穿
  • 用户量大量请求
  • 重试加大请求流量;
  • 用户重试
  • 代码逻辑重试
  • 服务调用者不可用;
  • 资源耗尽

3、雪崩效应应对策略

  • 应用扩容;
  • 升级硬件
  • 增加机器数量
  • 流控;
  • 限流
  • 关闭重试
  • 缓存;
  • 缓存预加载
  • 服务熔断;

二、如何容错

  • 1、为网络请求设置超时。
    避免因依赖服务不可用或者网络原因导致响应时间特别长,调用线程/进程无法释放资源,最后导致系统资源被耗尽,最终导致调用服务也不可用。
  • 2、使用断路器模式。
    类似于家里电流过载,会自动跳闸;
    如果对某个微服务的请求有大量超时,那么再对这个微服务请求就没有意义啦,可以认为该微服务不可用。这时断路器就会实现快速失败。
    断路器也可自动检测依赖的服务是否已经恢复正常。如果恢复正常啦,那么也会恢复请求该服务,通过这种方式实现微服务的“自我修复”;

即当依赖服务不正常时,通过断路器实现快速失败,避免雪崩效应;当依赖服务恢复正常时,又会恢复调用。

三、使用Hystrix实现容错

Hystrix是一个实现超时机制和断路器模式的工具类库。

1、Hystrix简介

Hystrix主要通过以下几点实现对服务的延迟和容错;

  • 包裹请求:使用HystrixCommand包裹对依赖的调用逻辑,每个命令都在独立的线程中执行,使用了设计模式中的“命令模式”;
  • 跳闸机制:当某服务的错误率超过一定的阈值时,Hystrix可以自动或者手动跳闸,停止请求该服务一段时间;
  • 资源隔离:Hystrix为每个依赖都维护了一个小型的线程池。如果该线程池已满,发往该依赖的所有请求都会被立刻拒绝,而不是排队等候,从而加速失败判定;
  • 监控:Hystrix可以近乎实时的监控运行指标和配置的变化,例如成功、失败、超时和被拒绝的请求等;
  • 回退机制:当请求失败、超时、被拒绝时,或者当断路器打开时,执行回退逻辑。回退逻辑有开发人员自行提供。
  • 自我修复:断路器打开一段时间后,进入“半开”状态。之后会调用该服务一个请求,如果成功,则恢复请求;否则,断路器再次打开;

2、整合Hystrix

Edgware.RELEASE的Spring Cloud版本;

  • 1、需要引入pom依赖
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
  • 2、Hystrix断路器开启

Hystrix服务添加@EnableCircuitBreaker或者@EnableHystrix,开启断路器支持

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

  public static void main(String[] args) {
    SpringApplication.run(ConsumerMovieApplication.class, args);
  }
}
  • 3、添加控制器

@HystrixCommand(fallbackMethod = “findByIdFallback”)通过注解使该方法具备容错能力;并编写回退方法findByIdFallback,该方法返回值需要与findById的类型一致。
注:因为Hystrix默认的超时时间是1秒,所以第一次用该功能时,无论怎么请求,返回的都是回退方法里默认的值,需要通过application配置修改一下超时时间。

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

  @HystrixCommand(fallbackMethod = "findByIdFallback")
  @GetMapping("/user/{id}")
  public User findById(@PathVariable Long id) {
    User user=this.restTemplate.getForObject("http://microservice-provider-user/" + id, User.class);
    return user;
  }

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

//可通过Throwable throwable获取对应的错误信息
//  public User findByIdFallback(Long id,Throwable throwable) {
//    LOGGER.info("进入回退方法:异常"+throwable);
//    User user = new User();
//    user.setId(-1L);
//    user.setName("默认用户"+throwable.getMessage());
//    return user;
//  }

}

  • 4、添加配置
#hystrix超时时间配置 (如果不配置的话默认是1000毫秒超时)
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 30000
  • 5、验证
    正常请求
    在这里插入图片描述
    断开服务提供者服务,即请求超时,返回的是回退请求中的值
    在这里插入图片描述

3、Hystrix核心配置

Hystrix核心配置可到该网页查看。

Hystrix本身组件超时设定如下,更多与其他组件配合使用时,Spring Cloud各组件超时总结

#hystrix超时时间配置 (如果不配置的话默认是1000毫秒超时)
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 30000

四、Feign开启Hystrix支持

1、开启

Feign默认不开启Hystrix功能,需要通过添加配置feign.hystrix.enabled=true完成功能开启;

2、指定回退类

很好理解,如下代码:

@FeignClient(name = "microservice-provider-user", fallback = FeignClientFallback.class)
public interface UserFeignClient {
  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public User findById(@PathVariable("id") Long id);

}

/**
 * 回退类FeignClientFallback需实现Feign Client接口
 * FeignClientFallback也可以是public class,没有区别
 */
@Component
class FeignClientFallback implements UserFeignClient {
  @Override
  public User findById(Long id) {
    User user = new User();
    user.setId(-1L);
    user.setUsername("默认用户");
    return user;
  }
}

3、指定回退类并输出原因

@FeignClient(name = "microservice-provider-user", fallbackFactory = FeignClientFallbackFactory.class)
public interface UserFeignClient {
  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public User findById(@PathVariable("id") Long id);
}

/**
 * UserFeignClient的fallbackFactory类,该类需实现FallbackFactory接口,并覆写create方法
 */
@Component
class FeignClientFallbackFactory implements FallbackFactory<UserFeignClient> {
  private static final Logger LOGGER = LoggerFactory.getLogger(FeignClientFallbackFactory.class);

  @Override
  public UserFeignClient create(Throwable cause) {
    return new UserFeignClient() {
      @Override
      public User findById(Long id) {
        // 日志最好放在各个fallback方法中,而不要直接放在create方法中。
        // 否则在引用启动时,就会打印该日志。

        FeignClientFallbackFactory.LOGGER.info("fallback; reason was:", cause);
        User user = new User();
        user.setId(-1L);
        user.setUsername("默认用户");
        return user;
      }
    };
  }
}

4、为Feign禁用Hystrix

  • 局部禁用
@Component
class FeignDisableHystrixConfiguration{
 @Bean
  @Scope("prototype")
  public Feign.Builder feignBuilder(){
   return Feign.builder();
 }

  @FeignClient(name = "user", configuration = FeignDisableHystrixConfiguration.class)
  public interface UserFeignClient {
  ...
  }
  • 全局禁用

feign.hystrix.enabled=false

五、Hystrix监控

1、Hystrix监控

引入依赖,通过注解开启Hystrix功能后,通过请求http://localhost:8010/hystrix.stream可以看到不断刷新的监控数据。

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

2、使用Hystrix Dashboard可视化监控

  • 引入依赖
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>
  • 开启功能

启动类添加注解@EnableHystrixDashboard

  • 测试
    在这里插入图片描述

在这里插入图片描述

3、使用Turbine聚合监控数据

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

开启Turbine功能:@EnableTurbine

  • 主要配置
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
turbine:
  appConfig: server-app1,server-app2 #(同样注册在注册中心服务上的应用服务)
  clusterNameExpression: "'default'" ## trubine集群名

通过上面的Hystrix Dashboard监控http://ip:port/turbine/stream即达到同时监控多个微服务的情况。

4、使用消息中间件收集数据

微服务应用集群—>MQ(例如rabbitMQ等)—>turbine server–>Hystrix Dashboard

  • 被监控Client端

添加依赖

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

连接rabbitMQ

spring:
  application:
      name: hystrix-mq
  rabbitmq:
    host: 10.132.XX.XX
    port: 5672
    username: admin
    password: admin
  • Turbine服务端
 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-turbine-stream</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>
server:
  port: 8031
spring:
  application:
    name: turbine
  rabbitmq:
    host: 10.132.XX.XX
    port: 5672
    username: admin
    password: admin
eureka:
  client:
    service-url:
      defaultZone: http://10.132.33.43:8761/eureka/
  instance:
    prefer-ip-address: true

在启动的Application中增加 @EnableTurbineStream 注解,即可在启动后自动从queue中搜集监控信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lwd2307997664

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值