(五)springcloud 断路器-Spring Cloud Netflix Hystrix

较低级别的服务中的服务故障可能导致级联故障一直到用户。 当对特定服务的调用超过circuitBreaker.requestVolumeThreshold(默认值:20个请求)且失败百分比大于circuit.rolllingStats.timeInMilliseconds定义的滚动窗口中的circuitBreaker.errorThresholdPercentage(默认值:> 50%)时(默认值:10秒)

设计原则:

  1. 防止单个服务的故障,耗尽整个系统服务的容器(比如tomcat)的线程资源,避免分布式环境里大量级联失败。通过第三方客户端访问(通常是通过网络)依赖服务出现失败、拒绝、超时或短路时执行回退逻辑
  2. 用快速失败代替排队(每个依赖服务维护一个小的线程池或信号量,当线程池满或信号量满,会立即拒绝服务而不会排队等待)和优雅的服务降级;当依赖服务失效后又恢复正常,快速恢复
  3. 提供接近实时的监控和警报,从而能够快速发现故障和修复。监控信息包括请求成功,失败(客户端抛出的异常),超时和线程拒绝。如果访问依赖服务的错误百分比超过阈值,断路器会跳闸,此时服务会在一段时间内停止对特定服务的所有请求
  4. 将所有请求外部系统(或请求依赖服务)封装到HystrixCommand或HystrixObservableCommand对象中,然后这些请求在一个独立的线程中执行。使用隔离技术来限制任何一个依赖的失败对系统的影响。每个依赖服务维护一个小的线程池(或信号量),当线程池满或信号量满,会立即拒绝服务而不会排队等待

功能特性:

  1. 请求熔断: 当Hystrix Command请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN)。这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN). Hystrix的断路器就像我们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力.
  2. 服务降级:Fallback相当于是降级操作. 对于查询操作, 可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存
  3. 依赖隔离(采用舱壁模式,Docker就是舱壁模式的一种):在Hystrix中, 主要通过线程池来实现资源隔离. 通常在使用的时候我们会根据调用的远程服务划分出多个线程池
  4. 请求缓存
  5. 请求合并

Ribbon集成断路器

1、基于之前的服务,引入Hystrix依赖

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

2、开启断路器功能

@EnableCircuitBreaker:加载断路器配置

@EnableCircuitBreaker

也可以使用@SpringCloudApplication注解:三合一

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}

3、创建fallback方法,指定为某个接口的降级

@SpringCloudApplication
public class ConsumerRibbonApplication {

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

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @RestController
    @RequestMapping("/api/v1/consumer")
    class ProviderController {

        private static final String SERVICE_NAME = "provider-server";
        private static final String GET_PORT = "/api/v1/provider/port";

        @Resource
        private RestTemplate restTemplate;

        @GetMapping
        @HystrixCommand(fallbackMethod = "consumerFallback")
        public String consumer() {
            ResponseEntity<String> forEntity = restTemplate.getForEntity("http://" + SERVICE_NAME + GET_PORT, String.class, (Object) null);
            return forEntity.getBody();
        }

        public String consumerFallback() {
            return "provider error";
        }

    }

}

hystrix:配置

hystrix:
  command:
    default:
      execution:
        isolation:
          strategy: SEMAPHORE
          thread:
            timeoutInMilliseconds: 60000
  shareSecurityContext: true

验证:

访问消费者:http://localhost:3000/api/v1/consumer

获得响应:2000

Feign集成断路器

引入依赖和开启配置和Ribbon一样

1、在@FeignClient上声明

@FeignClient(name = "provider-server", fallback = ProviderClientFallback.class)
@RequestMapping("/api/v1/provider")
public interface ProviderClient {

    @GetMapping("/port")
    String port();

}

2、开启配置feign.hystrix.enabled=true

server:
  port: 3001
spring:
  application:
    name: consumer-server-feign
  profiles:
    active: dev
  cloud:
    config:
      label: master
      profile: ${spring.profiles.active}
      discovery:
        service-id: config-server
        enabled: true

feign:
  hystrix:
    enabled: true

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka/

3、编写fallback类

public class ProviderClientFallback implements ProviderClient {

    @Override
    public String port() {
        return "provider error";
    }

}

4、在声明类@FeignClient上指定fallback属性

@FeignClient(name = "provider-server", fallback = ProviderClientFallback.class)
@RequestMapping("/api/v1/provider")
public interface ProviderClient {

    @GetMapping("/port")
    String port();

}

验证:

访问消费者:http://localhost:3000/api/v1/consumer

获得响应:2000

关闭生产者服务:http://localhost:3000/api/v1/consumer

获得响应:provider error

5、换成指定FallbackFactory,可以获取到异常对象

@FeignClient(name = "provider-server",
        fallbackFactory = HystrixClient.HystrixClientFallback.class,
        path = "/api/v1/provider")
public interface HystrixClient {

    @GetMapping("/port")
    String port();

    @Component
    class HystrixClientFallback implements FallbackFactory<HystrixClient> {

        @Override
        public HystrixClient create(Throwable throwable) {
            return new HystrixClient() {
                @Override
                public String port() {
                    return "provider error: " + throwable;
                }
            };
        }
    }
}

验证:

访问消费者:http://localhost:3000/api/v1/consumer

获得响应:2000

关闭生产者服务:http://localhost:3000/api/v1/consumer

获得响应:provider error: java.lang.RuntimeException: com.netflix.client.ClientException: Load balancer does not have available server for client: provider-server

Hystrix Metrics Stream

包含依赖关系spring-boot-starter-actuator,设置 management.endpoints.web.exposure.include: hystrix.stream。这样做会将/actuator/hystrix.stream管理端点公开

依赖:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

配置:

# 全部开放监控端点
management:
  endpoints:
    web:
      exposure:
        include: "*"

验证:

GET /actuator/metrics
GET /actuator/metrics/{requiredMetricName}
{[/actuator/metrics/{requiredMetricName}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
{[/actuator/metrics],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 

断路器:Hystrix仪表板

1、添加依赖项:spring-cloud-starter-netflix-hystrix-dashboard

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

2、使用@EnableHystrixDashboard注解开启仪表盘

@EnableFeignClients
@SpringCloudApplication
@EnableHystrixDashboard
public class ConsumerFeignApplication {
}

3、访问/hystrix并将仪表板指向/hystrix.streamHystrix客户端应用程序中的单个实例的端点。

  • http://localhost:3001/hystrix
  • https://localhost:3001/hystrix/hystrix.stream

猜你喜欢

转载自www.cnblogs.com/zuier/p/10768075.html