本文转载自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

hystrix(一) 简单使用, 以及动态配置更新的更多相关文章

  1. 通过Dapr实现一个简单的基于.net的微服务电商系统(十七)——服务保护之动态配置与热重载

    在上一篇文章里,我们通过注入sentinel component到apigateway实现了对下游服务的保护,不过受限于目前变更component需要人工的重新注入配置以及重启应用更新componen ...

  2. 【架构篇】ASP.NET Core 基于 Consul 动态配置热更新

    背景 通常,.Net 应用程序中的配置存储在配置文件中,例如 App.config.Web.config 或 appsettings.json.从 ASP.Net Core 开始,出现了一个新的可扩展 ...

  3. Quartz实现分布式可动态配置的定时任务

    关键词: 1. 定时任务 2. 分布式 3. 可动态配置触发时间 一般通过Quartz实现定时任务很简单.如果实现分布式定时任务需要结合分布式框架选择master节点触发也可以实现.但我们有个实际需求 ...

  4. springboot整合Quartz实现动态配置定时任务

    前言 在我们日常的开发中,很多时候,定时任务都不是写死的,而是写到数据库中,从而实现定时任务的动态配置,下面就通过一个简单的示例,来实现这个功能. 一.新建一个springboot工程,并添加依赖 & ...

  5. Zookeeper C++编程实战之配置更新

    CZookeeperHelper:https://github.com/eyjian/libmooon/blob/master/include/mooon/net/zookeeper_helper.h ...

  6. nginx动态配置及服务发现那些事

    Reference: http://xiaorui.cc/2016/10/16/nginx%E5%8A%A8%E6%80%81%E9%85%8D%E7%BD%AE%E5%8F%8A%E6%9C%8D% ...

  7. Quartz实现JAVA定时任务的动态配置

    什么是动态配置定时任务? 首先说下这次主题,动态配置.没接触过定时任务的同学可以先看下此篇:JAVA定时任务实现的几种方式 定时任务实现方式千人千种,不过基础的无外乎 1.JDK 的Timer类 2. ...

  8. ZooKeeper动态配置(十四)

    概述 在3.5.0发行之前,ZK的全体成员和所有其它的配置参数是静态加载的在启动的时候并且在运行的时候不可变.操作员诉诸于"滚动重启" - 一个手动密集和改变配置文件容易出错的方法 ...

  9. 新手学分布式 - Envoy Proxy XDS Server动态配置的一点使用心得

    Envoy Proxy 动态API的使用总结 Envoy Proxy和其它L4/L7反向搭理工具最大的区别就是原生支持动态配置. 首先来看一下Envoy的大致架构 从上图可以简单理解:Listener ...

随机推荐

  1. php定界符介绍

    php界定符就是为了照样输出内容.它的格式如下: <<<EOF ...... EOF; 其中EOF是自定义的变量,但要成对出现! 首先附上一段php代码: <?php $a = ...

  2. undefined reference to `udev_device_get_action'

    /usr/lib/gcc/i686-linux-gnu/4.8/../../../i386-linux-gnu/libusb-1.0.a(libusb_1_0_la-linux_udev.o): In ...

  3. 实战 | 源码入门之Faster RCNN

    前言 学习深度学习和计算机视觉,特别是目标检测方向的学习者,一定听说过Faster Rcnn:在目标检测领域,Faster Rcnn表现出了极强的生命力,被大量的学习者学习,研究和工程应用.网上有很多 ...

  4. django考点

    django考点 1 列举Http请求中常见的请求方式2 谈谈你对HTTP协议的认识.1.1 长连接3 简述MVC模式和MVT模式4 简述Django请求生命周期5 简述什么是FBV和CBV6 谈一谈 ...

  5. Java基础 @org.junit.Test-单元测试方法 + 操纵Collection和Map的工具类 : Collections 的sort/binarySearch/max/min等静态方法

      单元测试代码:  ( 在IDEA中先输入'@Test '然后根据提示进行自动修订即可!!运行时直接运行即可! 若有多个单元测试块的时候,直接把鼠标放在哪里就自动在哪里运行那个单元块) import ...

  6. Java基础 String/StringBuff/StringBuilder 常用操作方法复习/内存分析/三者的效率比较

    附:jdk1.8使用IDEA安装.创建.使用JUnit单元测试 笔记总结: /**String 复习 * 1.像C++这样的char arr[]="..." 的方式无法声明Java ...

  7. Redis做消息队列

    1.连接从Redis中获取日志文件并存储到ES中 [root@Logstash ~]# vim /usr/local/logstash/config/redis.conf input {     be ...

  8. python_反射:动态导入模块

    官方推荐方法: test_mod.py def hi(): print('Hi') test.py import importlib q = importlib.import_module('test ...

  9. linux实操_shell流程控制

    if判断: 基本语法: if [ 条件判断式 ] then 程序 elif [ 条件判断式 ] then 程序 fi 实例:请编写一个shell程序,如果输入的参数,大于60,则输出“及格了”,如果小 ...

  10. git中的基本命令

    工作区:      当前的编辑位置 缓存区:      add 之后的区域 版本库:      commit之后的区域就是版本库 git init .         初始化 git add .    ...