Hystrix——服务容错

作者: JacobY | 来源:发表于2018-01-17 18:11 被阅读1555次

    1 Hystrix 简介

    在微服务架构中,微服务之间通过网络进行通信,存在相互依赖,当其中一个服务不可用时,有可能会造成雪崩效应。要防止这样的情况,必须要有容错机制来保护服务。
    Hystrix是Netflix开源的一个延迟和容错库,它主要实现了以下几点:

    • 包裹请求
      使用HystrixCommand(或HystrixObservableCommand)包裹对依赖的调用逻辑,每个命令在独立线程中执行。
    • 跳闸机制
      当某服务的错误率超过一定阈值时,Hystrix可以自动或手动跳闸,停止请求该服务一段时间。
    • 资源隔离
      Hystrix为每个依赖都维护了一个小型的线程池(或信号量),如果该线程池已满,发往该依赖的请求就被立即拒绝。
    • 监控
      Hystrix可以近乎实时地监控运行指标和配置的变化。
    • 回退机制
      当请求失败、超时、被拒绝,或者当断路器打开时,执行回退逻辑。
    • 自我修复
      当断路器打开一段时间后,会自动进入“半打开”状态,允许一个请求访问依赖的服务,如果该请求成功,则关闭断路器,否则继续保持打开状态。

    2 整合Hystrix

    2.1 Ribbon整合Hystrix

    1.添加相应的依赖:

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

    2.在启动类里添加@EnableCircuitBreaker 或者 @EnableHystrix注解

    @EnableCircuitBreaker
    @EnableDiscoveryClient
    @SpringBootApplication
    public class RibbonDemoApplication {
    
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    
    
    
        public static void main(String[] args) {
            SpringApplication.run(RibbonDemoApplication.class, args);
        }
    }
    

    3.为需要容错的方法添加@HystrixCommand注解,并使用fallbackMethod属性指定回退方法

        @HystrixCommand(fallbackMethod = "errorFallback")
        @GetMapping("/hello")
        public String hello() {
    
            return this.restTemplate.getForObject("http://eureka-client-demo/hello", String.class);
        }
    
    
        public String errorFallback() {
            return "Error!";
        }
    

    @HystrixCommand的配置类似下面:

    @HystrixCommand(fallbackMethod = "stubMyService",
        commandProperties = {
          @HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE")
        }
    )
    

    2.2 Feign使用Hystrix

    1.Spring Cloud 中,Feign默认已经整合了Hystrix,所以只需要在配置中启用Hystrix就会包裹全部Feign Client中的方法:

    feign:
      hystrix:
        enabled: true
    

    2.编写回退方法,编写一个Feign Client的实现类,在@FeignClient的fallback属性指定对应的类:

    @FeignClient(name = "eureka-client-demo", fallback = ErrorFallback.class)
    public interface DemoFeignClient {
    
        @GetMapping("/hello")
        public String hello();
    }
    
    
    @Component
    public class ErrorFallback implements DemoFeignClient {
    
        @Override
        public String hello() {
            return "Error!";
        }
    }
    

    3.如果需要回退方法打印错误信息,可以使用fallbackFactory(fallback和fallbackFactory只能使用其中一种):

    @FeignClient(name = "eureka-client-demo", fallbackFactory = ErrorFallbackFactory.class)
    public interface DemoFeignClient {
    
        @GetMapping("/hello")
        public String hello();
    }
    
    
    @Component
    public class ErrorFallbackFactory implements FallbackFactory<DemoFeignClient> {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(ErrorFallbackFactory.class);
    
        @Override
        public DemoFeignClient create(Throwable throwable) {
            return new DemoFeignClient() {
                @Override
                public String hello() {
                    //如果在create()中打印错误信息的话,在应用程序启动时就会打印
                    ErrorFallbackFactory.LOGGER.info("fall back cause: ", throwable);
                    return "Error!";
                }
            };
        }
    }
    
    

    4.如果不想某个Feign Client使用Hystrix的话,可以使用如下配置:

    @FeignClient(name = "eureka-client-demo", configuration = DisableHystrix.class)
    public interface DemoFeignClient {
    
        @GetMapping("/hello")
        public String hello();
    }
    
    @Configuration
    public class DisableHystrix {
    
        @Bean
        @Scope("prototype")
        public Feign.Builder feignBuilder() {
            return Feign.builder();
        }
    }
    

    3 Hystrix监控

    3.1 Ribbon中Hystrix的监控

    Hystrix提供了端点/hystrix.stream用于监控Hystrix的情况,Ribbon在整合了Hystrix之后,还需要引入Spring Boot 的actuator依赖,才能通过/hystrix.stream监控接口运行情况。

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

    /hystrix.stream的页面会返回类似下面的监控数据:

    data: {"type":"HystrixCommand","name":"hello","group":"Controller","currentTime":1516202320578,"isCircuitBreakerOpen":false,"errorPercentage":100,"errorCount":1,"requestCount":1,"rollingCountBadRequests":0,"rollingCountCollapsedRequests":0,"rollingCountEmit":0,"rollingCountExceptionsThrown":0,"rollingCountFailure":1,"rollingCountFallbackEmit":0,"rollingCountFallbackFailure":0,"rollingCountFallbackMissing":0,"rollingCountFallbackRejection":0,"rollingCountFallbackSuccess":1,"rollingCountResponsesFromCache":0,"rollingCountSemaphoreRejected":0,"rollingCountShortCircuited":0,"rollingCountSuccess":0,"rollingCountThreadPoolRejected":0,"rollingCountTimeout":0,"currentConcurrentExecutionCount":0,"rollingMaxConcurrentExecutionCount":0,"latencyExecute_mean":0,"latencyExecute":{"0":0,"25":0,"50":0,"75":0,"90":0,"95":0,"99":0,"99.5":0,"100":0},"latencyTotal_mean":0,"latencyTotal":{"0":0,"25":0,"50":0,"75":0,"90":0,"95":0,"99":0,"99.5":0,"100":0},"propertyValue_circuitBreakerRequestVolumeThreshold":20,"propertyValue_circuitBreakerSleepWindowInMilliseconds":5000,"propertyValue_circuitBreakerErrorThresholdPercentage":50,"propertyValue_circuitBreakerForceOpen":false,"propertyValue_circuitBreakerForceClosed":false,"propertyValue_circuitBreakerEnabled":true,"propertyValue_executionIsolationStrategy":"THREAD","propertyValue_executionIsolationThreadTimeoutInMilliseconds":1000,"propertyValue_executionTimeoutInMilliseconds":1000,"propertyValue_executionIsolationThreadInterruptOnTimeout":true,"propertyValue_executionIsolationThreadPoolKeyOverride":null,"propertyValue_executionIsolationSemaphoreMaxConcurrentRequests":10,"propertyValue_fallbackIsolationSemaphoreMaxConcurrentRequests":10,"propertyValue_metricsRollingStatisticalWindowInMilliseconds":10000,"propertyValue_requestCacheEnabled":true,"propertyValue_requestLogEnabled":true,"reportingHosts":1,"threadPool":"Controller"}

    3.2 Feign中Hystrix的监控

    1.虽然Feign整合了Hystrix,但是并没有整合到监控的模块,所以我们需要重新引入依赖包:

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

    2.在启动类添加@EnableCircuitBreaker或者@EnableHystrix注解

    @EnableCircuitBreaker
    @EnableDiscoveryClient
    @EnableFeignClients
    @SpringBootApplication
    public class FeignDemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(FeignDemoApplication.class, args);
        }
    }
    

    然后就可以通过端点/hystrix.stream查看监控数据。

    4 可视化监控

    4.1 监控单个服务

    可以使用hystrix-dashboard进行可视化监控:
    1.创建一个新项目,并引入以下依赖:

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
            </dependency>
    
    1. 在启动类加上@EnableHystrixDashboard注解
    @EnableHystrixDashboard
    @SpringBootApplication
    public class HystrixDashboardApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(HystrixDashboardApplication.class, args);
        }
    }
    

    3.启动应用,打开/hystrix/端点,可以看到一下页面:

    hystix-dashboard.PNG
    往url栏输入/hystrix.stream的链接,如:http://localhost:8004/hystrix.stream,再点击Monitor Stream按钮,就可以看到如下图的页面:
    hystix-dashboard-detail.PNG

    4.2 监控多个服务

    上面的方法只能监控单个服务,如果要监控多个服务,可以使用turbine,然后再使用hystrix-dashboard进行进行可视化监控。
    1.新建一个项目,引入turbine的依赖

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

    2.在启动类添加@EnableTurbine注解

    @EnableTurbine
    @SpringBootApplication
    public class TurbineApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(TurbineApplication.class, args);
        }
    }
    

    3.配置文件:

    server:
      port: 8006
    spring:
      application:
        name: turbine
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8001/eureka/
      instance:
        prefer-ip-address: true
    
    turbine:
      app-config: feign-demo,ribbon-demo
      cluster-name-expression: "'default'"
      combine-host-port: true
    
    • app-config 指定需要监控的服务,用逗号分隔
    • cluster-name-expression 指定集群名称
    • combine-host-port 按主机名和端口区分服务,turbine默认相同host的为同一服务,将该属性设为true后就可以按主机名和端口区分服务

    4.启动应用,打开/turbine.stream端点即可以看到两者的监控数据。这个时候,再将turbine的监控数据接入hystrix-dashboard,比如,将url地址http://localhost:8006/turbine.stream填入dash-board的url一栏,再点击Monitor Stream按钮,就可以同时看到两个服务的监控数据。

    4.3 使用消息中间件收集数据(RabbitMQ)

    1. 提供服务的微服务添加以下依赖:
            <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>
    
    1. 添加RabbitMQ的配置:
    spring:
      rabbitmq:
        host: localhost
        port: 5672
        username: guest
        password: guest
    
    1. Turbine项目移除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>
    
    1. 启动类中@EnableTurbine修改为@EnableTurbineStream
    2. 添加RabbitMQ的配置,同2,同时去掉turbine的配置。

    相关文章

      网友评论

        本文标题:Hystrix——服务容错

        本文链接:https://www.haomeiwen.com/subject/lueuoxtx.html