zoukankan      html  css  js  c++  java
  • hystrix(一) 简单使用, 以及动态配置更新

    本文转载自https://my.oschina.net/u/1169457/blog/1787414

    hystrix 简单使用, 以及动态配置更新

    概述

    只介绍同步模式下简单的使用, 有助于快速接入, 会有一些官方文档中没有涉及的细节.

    默认方式

    HelloWorld!

    public class CommandHelloWorld extends HystrixCommand<String> {
    
        private final String name;
    
        // 构造方法中传入需要用到的数据, run 方法处理逻辑.
        public CommandHelloWorld(String name) {
            // 构造 Setter 比较麻烦, 后面会进一步介绍
            super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
            this.name = name;
        }
    
        @Override
        protected String run() {
            // a real example would do work like a network call here
            return "Hello " + name + "!";
        }
        
        // fallback 方法可选, 如果没有, 默认抛异常.
        @Override
        protected String getFallback() {
            return "fallback";
        }
    }

    构造Setter

    Hystrix 讲求的大而全, 设计的比较模式, 用起来不是很方便. 下面是一个构造 Setter 的实例:

    Setter setter = Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(site)) // groupKey 对command进行分组, 用于 reporting, alerting, dashboards, or team/library ownership, 也是 ThreadPool 的默认 key
            .andCommandKey(HystrixCommandKey.Factory.asKey(site)) // 可以根据 commandKey 具体的运行时参数
            .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(site))  // 指定 ThreadPool key, 这样就不会默认使用 GroupKey
            .andCommandPropertiesDefaults(HystrixCommandProperties.Setter() // 初始化 Command 相关属性
                    .withMetricsRollingStatisticalWindowInMilliseconds(
                            100 * 1000) // 设置统计窗口为100秒
                    .withCircuitBreakerSleepWindowInMilliseconds(
                            10 * 1000) // 设置熔断以后, 试探间隔为10秒
                    .withCircuitBreakerRequestVolumeThreshold(
                            10) // 设置判断熔断请求阈值为10
                    .withCircuitBreakerErrorThresholdPercentage(
                            80) // 设置判断熔断失败率为80%
                    .withExecutionTimeoutInMilliseconds(3 * 1000)) // 设置每个请求超时时间为3秒
            .andThreadPoolPropertiesDefaults( // 设置和threadPool相关
                    HystrixThreadPoolProperties.Setter().withCoreSize(20)); // 设置 threadPool 大小为20(最大20个并发)

    另外 threadPool 还有个设置统计窗口的选项, 因为 Hystrix 统计维度会从主线程和线程池两个维度来统计.

    还有好多配置信息可以配置, 这里只提供了几个重要的. 其他配置参考:hystrix-configuration

    Spring cloud 注解方式

    需要用到两个注解: @EnableCircuitBreaker@HystrixCommand(fallbackMethod = "reliable")

    启动类:

    package hello;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.web.client.RestTemplateBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
    import org.springframework.web.client.RestTemplate;
    
    @EnableCircuitBreaker
    @RestController
    @SpringBootApplication
    public class ReadingApplication {
    
      @Autowired
      private BookService bookService;
    
      @Bean
      public RestTemplate rest(RestTemplateBuilder builder) {
        return builder.build();
      }
    
      @RequestMapping("/to-read")
      public String toRead() {
        return bookService.readingList();
      }
    
      public static void main(String[] args) {
        SpringApplication.run(ReadingApplication.class, args);
      }
    }
    服务类:
    
    package hello;
    
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import org.springframework.stereotype.Service;
    import org.springframework.web.client.RestTemplate;
    
    import java.net.URI;
    
    @Service
    public class BookService {
    
      private final RestTemplate restTemplate;
    
      public BookService(RestTemplate rest) {
        this.restTemplate = rest;
      }
    
      @HystrixCommand(fallbackMethod = "reliable")
      public String readingList() {
        URI uri = URI.create("http://localhost:8090/recommended");
    
        return this.restTemplate.getForObject(uri, String.class);
      }
    
      public String reliable() {
        return "Cloud Native Java (O'Reilly)";
      }
    
    }

    动态更新配置

    Hystrix 使用 Archaius 来实现动态配置. 使用 Spring 配置方式:

    1. 创建配置获取源
    2. 配置并初始化自动配置

    创建配置获取源

    实现接口 PolledConfigurationSource, 并返回一个 Map. 注意 Key 为 hystrix 配置key, 可以参考: Hystrix-configuration

    package com.rh.config.hystrix;
    
    import com.netflix.config.PollResult;
    import com.netflix.config.PolledConfigurationSource;
    import org.springframework.core.env.*;
    import org.springframework.core.io.ResourceLoader;
    import org.springframework.stereotype.Component;
    
    
    import javax.annotation.Resource;
    import java.util.*;
    
    /**
     * @Auther: wangyunfei
     * @Date: 2019/12/10 14:12
     * @Description:
     */
    @Component
    /**
     * @Author wangyunfei
     * @Description 定期读取配置文件中的hystrix配置
     * @Date 2019/12/10 14:13
     * @Param
     * @return
     **/
    public class DegradeConfigSource implements PolledConfigurationSource {
        public final String HystrixPrefix = "hystrix";
    
        //spring的Environment
        private ConfigurableEnvironment environment;
        private PropertySourcesPropertyResolver resolver;
    
        DegradeConfigSource(ConfigurableEnvironment environment) {
            this.environment = environment;
            this.resolver = new PropertySourcesPropertyResolver(this.environment.getPropertySources());
            this.resolver.setIgnoreUnresolvableNestedPlaceholders(true);
    
        }
        
        @Override
        public PollResult poll(boolean initial, Object checkPoint) throws Exception {
            //Map<String, Object> complete = getHystrixConfig();
            Map<String, Object> complete = getProperties();
            return PollResult.createFull(complete);
        }
    
        @Resource
        private ResourceLoader resourceLoader;
        /**
         * @Author wangyunfei
         * @Description 获取配置文件中的指定hystrix前缀信息
         * 缺点:1)不支持yml格式 只支持properties
         *       2)只能读取某一个配置文件中的信息 如果配置是写在不同配置文件则不支持
         * @Date 2019/12/20 14:58
         * @Param []
         * @return java.util.HashMap<java.lang.String,java.lang.String>
         **/
        public HashMap<String,Object> getHystrixConfig() throws Exception
        {
            HashMap<String,Object> hystrixMap = new  HashMap<String,Object>();
            org.springframework.core.io.Resource resource = resourceLoader.getResource("classpath:application-mod.properties");
            Properties props = new Properties();
            props.load(resource.getInputStream());
            Enumeration keys = props.propertyNames();
            while (keys.hasMoreElements()) {
                String key = (String) keys.nextElement();
                System.out.println(key + "=" + props.getProperty(key));
                if(key.contains(HystrixPrefix))
                {
                    hystrixMap.put(key, props.getProperty(key));
                }
            }
            return hystrixMap;
        }
    
        /**
         * @Author wangyunfei
         * @Description 获取所有配置信息
         * @Date 2019/12/20 15:06
         * @Param []
         * @return java.util.Map<java.lang.String,java.lang.Object>
         **/
        public Map<String, Object> getProperties() {
            Map<String, Object> properties = new LinkedHashMap<>();
            //spring env 里面也是多个source组合的
            for (Map.Entry<String, PropertySource<?>> entry : getPropertySources().entrySet()) {
                PropertySource<?> source = entry.getValue();
                if (source instanceof EnumerablePropertySource) {
                    EnumerablePropertySource<?> enumerable = (EnumerablePropertySource<?>) source;
                    for (String name : enumerable.getPropertyNames()) {
                        if (!properties.containsKey(name) && name.contains(HystrixPrefix)) {
                            properties.put(name, resolver.getProperty(name));
                        }
                    }
                }
            }
            return properties;
        }
    
        //PropertySource也可能是组合的,通过递归获取
        private Map<String, PropertySource<?>> getPropertySources() {
            Map<String, PropertySource<?>> map = new LinkedHashMap<String, PropertySource<?>>();
            MutablePropertySources sources = null;
            if (environment != null) {
                sources = environment.getPropertySources();
            } else {
                sources = new StandardEnvironment().getPropertySources();
            }
            for (PropertySource<?> source : sources) {
                extract("", map, source);
            }
            return map;
        }
    
        private void extract(String root, Map<String, PropertySource<?>> map,
                             PropertySource<?> source) {
            if (source instanceof CompositePropertySource) {
                for (PropertySource<?> nest : ((CompositePropertySource) source)
                        .getPropertySources()) {
                    extract(source.getName() + ":", map, nest);
                }
            } else {
                map.put(root + source.getName(), source);
            }
        }
    }

    配置并初始化自动配置

    创建一个 DynamicConfiguration, 并注册一下就可以了. 注意, 我们使用了 FixedDelayPollingScheduler 来定期加载新的配置. 默认60秒加载一次.

    @Configuration
    public class DegradeDynamicConfig {
    
        @Bean
        public DynamicConfiguration dynamicConfiguration(@Autowired DegradeConfigSource degradeConfigSource) {
            AbstractPollingScheduler scheduler = new FixedDelayPollingScheduler(30 * 1000, 60 * 1000, false);
            DynamicConfiguration configuration = new DynamicConfiguration(degradeConfigSource, scheduler);
            ConfigurationManager.install(configuration); // must install to enable configuration
            return configuration;
        }
    
    }
    其中从配置文件获取hystrix配置信息等参考如下代码  http://techblog.ppdai.com/2018/05/08/20180508/
     

    参考

    Hystrix-how-to-use
    Hystrix-configuration
    Hystrix-change-config-dynamically
    hystrix-archaius-to-dynamic-config
    Spring-circuit-breaker

  • 相关阅读:
    asp.net 启动关闭iis
    vue 界面关闭触发事件 ---实例销毁之前调用
    ElmentUI 设置禁止点击遮罩关闭 el-dialog 弹窗
    C#反射
    SQL Server 创建游标(cursor)
    文件解压缩
    文件流操作
    Linq查询
    C#线程 多线程 进程
    匿名类型和反射
  • 原文地址:https://www.cnblogs.com/king1302217/p/12016353.html
Copyright © 2011-2022 走看看