Spring cloud 之熔断机制

本文涉及的产品
网络型负载均衡 NLB,每月750个小时 15LCU
传统型负载均衡 CLB,每月750个小时 15LCU
应用型负载均衡 ALB,每月750个小时 15LCU
简介: Spring cloud组件的熔断机制

前面讲过Spring cloud 之多种方式限流来处理请求频繁的压力。大家都知道,多个微服务之间调用的时候,假设微服务 A 调用微服务 B 和微服务 C,微服务 B 和微服务 C 有调用其他的微服务,这就是所谓的 扇出,若扇出的链路上某个微服务的请求时间过长或者不可用,对微服务 A 的调用就会占用越来越多的时间以及更多资源,进而引起系统雪崩,即”雪崩效应”。

这个时候,需要一个机制来保证当某个微服务出现异常时(请求反应慢或宕机),其整个流程还是阔以友好滴进行下去。即向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就可以保证调用方的线程不会被长时间、无厘头滴占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。我们把这个机制,或者这种处理方式叫作“熔断器”。

熔断机制是应对雪崩效应的一种微服务链路保护机制,当整个链路的某个微服务异常时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回“合理”的响应信息。当检测到该节点微服务正常后恢复调用链路,在Spring cloud 框架机制通过 Hystrix 实现,Hystrix 会监控微服务见调用的状况,当失败的调用到一个阈值,默认是5秒内20次调用失败就会启动熔断机制,熔断机制的注解是 @HystrixCommand

最近研究了一下 Spring cloud 的熔断机制,特分享一些代码,以及实战中的坑。

在Spring cloud 中,假设有几个微服务:用户管理服务、订单服务、鉴权中心、物流服务等。这时,订单服务中,某个接口请求用户管理服务,这个时候如果需要熔断机制,该怎么处理呢?

首先,订单服务引入依赖:


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

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

这个时候,订单服务启动类中需要引用熔断注解 @EnableCircuitBreaker,使其生效:

/**
 * @author Damon
 * @date 2020年1月13日 下午3:23:06
 *
 */

@EnableOAuth2Sso
@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackages = {"com.damon"})
@EnableDiscoveryClient
@EnableCircuitBreaker
public class OrderApp {

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

}

这里,不要忘记注解 @EnableDiscoveryClient 来相互暴露服务。

最后需要在调用用户管理服务的函数中,加入注解 @HystrixCommand:

@HystrixCommand(fallbackMethod = "admin_service_fallBack", commandProperties = {
      @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000") })//隔离策略:execution.isolation.strategy =SEMAPHORE or THREAD(不配置默认)
  @Override
  public Response<Object> getUserInfo(HttpServletRequest req, HttpServletResponse res) {

    ResponseEntity<String> forEntity = restTemplate.getForEntity(envConfig.getAdmin_web_url() + "/api/user/getUserInfo", String.class);
    HttpHeaders headers = new HttpHeaders();
    MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
    headers.setContentType(type);
    headers.add("Accept", MediaType.APPLICATION_JSON.toString());
    headers.add("Authorization", "bearer " + StrUtil.subAfter(req.getHeader("Authorization"), "bearer ", false));
    HttpEntity<String> formEntity = new HttpEntity<String>(null, headers);
    String body = "";
    try {
      ResponseEntity<String> responseEntity = restTemplate.exchange("http://admin-web-service/api/user/getUserInfo",
          HttpMethod.GET, formEntity, String.class);
      if (responseEntity.getStatusCodeValue() == 200) {
        logger.debug(String.format("request getUserInfo return: {}", JSON.toJSON(responseEntity.getBody())));
        return Response.ok(responseEntity.getStatusCodeValue(), 0, "success", JSON.toJSON(responseEntity.getBody()));
      }
    } catch (Exception e) {
      logger.error("loadJobDetail error");
      logger.error(e.getMessage(), e);
    }
    return null;
  }


  private Response<Object> admin_service_fallBack(HttpServletRequest req, HttpServletResponse res) {
    String token = StrUtil.subAfter(req.getHeader("Authorization"), "bearer ", false);
    logger.info("admin_service_fallBack token: {}", token);
    return Response.ok(200, -2, "用戶服務掛啦!", null);
  }

其中上面代码需要注意的是:注解中 fallbackMethod 的值指定了熔断后的处理函数,这个函数的参数与当前的调用方法的参数需要保持一致,否则报错:

com.netflix.hystrix.contrib.javanica.exception.FallbackDefinitionException:fallback method wasn't found.

最后,配置 Hystrix 相关的参数配置yaml:

hystrix.command.BackendCall.execution.isolation.thread.timeoutInMilliseconds: 5000
hystrix.threadpool.BackendCallThread.coreSize: 5

其中第一个配置在调用函数中其实也可以配置:

@HystrixCommand(fallbackMethod = "admin_service_fallBack", commandProperties = {
      @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000") })

这里配置的3000毫秒生效后,如果配置文件中也配置了,则会被覆盖。

如果不加@HystrixCommand中的commandProperties=@HystrixProperty注解配置,下面的FallBack函数admin_service_fallBack()是一个线程;@HystrixCommand()是一个隔离线程。若加上commandProperties=@HystrixProperty注解配置后,将2个线程合并到一个线程里。

这样到此为止,调用方就结束配置了,这里的http://admin-web-service为被调用服务,则在其服务启动类中需要注解 @EnableDiscoveryClient:

@EnableOAuth2Sso
@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackages = {"com.damon"})
@EnableConfigurationProperties(EnvConfig.class)
@EnableDiscoveryClient
public class AdminApp {

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

}

另外,配置 RestTemplate 的 Bean 中加上注解 @LoadBalanced 需要作 LB,这样利用服务名来根据 LB 规则找到对应的其中一个服务,这样比较明显看出 LB 的效果:

@Configuration
public class BeansConfig {
  @Resource
  private Environment env;

  @LoadBalanced//就不能用ip等形式来请求其他服务
  @Bean
  public RestTemplate restTemplate() {
    SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
    requestFactory.setReadTimeout(env.getProperty("client.http.request.readTimeout", Integer.class, 15000));
    requestFactory.setConnectTimeout(env.getProperty("client.http.request.connectTimeout", Integer.class, 3000));
    RestTemplate rt = new RestTemplate(requestFactory);
    return rt;
  }

}

最后如果没问题了,可以先暂停用户管理服务,然后运行订单服务时,返回熔断结果:

{"message":{"code":-2,"message":"用戶服務掛啦!","status":200}}
相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
5月前
|
监控 负载均衡 Java
深入理解Spring Cloud中的服务网关
深入理解Spring Cloud中的服务网关
|
23天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
60 2
|
2月前
|
监控 Java 微服务
spring 熔断机制
spring 熔断机制
50 0
|
3月前
|
XML 监控 Java
Spring Cloud全解析:熔断之Hystrix简介
Hystrix 是由 Netflix 开源的延迟和容错库,用于提高分布式系统的弹性。它通过断路器模式、资源隔离、服务降级及限流等机制防止服务雪崩。Hystrix 基于命令模式,通过 `HystrixCommand` 封装对外部依赖的调用逻辑。断路器能在依赖服务故障时快速返回备选响应,避免长时间等待。此外,Hystrix 还提供了监控功能,能够实时监控运行指标和配置变化。依赖管理方面,可通过 `@EnableHystrix` 启用 Hystrix 支持,并配置全局或局部的降级策略。结合 Feign 可实现客户端的服务降级。
187 23
|
5月前
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
Spring Cloud Alibaba 发布了 Scheduling 任务调度模块 [#3732]提供了一套开源、轻量级、高可用的定时任务解决方案,帮助您快速开发微服务体系下的分布式定时任务。
15020 33
|
4月前
|
负载均衡 监控 Java
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
|
4月前
|
Java 开发工具 Spring
Spring的Factories机制介绍
Spring的Factories机制介绍
82 1
|
5月前
|
负载均衡 Java Spring
Spring cloud gateway 如何在路由时进行负载均衡
Spring cloud gateway 如何在路由时进行负载均衡
543 15
|
5月前
|
Java Spring
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
117 3