【Spring Boot】 Spring Boot之Hystrix使用介绍
一、Maven依赖
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!-- hystrix --> <dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-core</artifactId> <version>1.5.18</version> </dependency> <dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-javanica</artifactId> <version>1.5.18</version> </dependency> <dependency> <groupId>de.ahus1.prometheus.hystrix</groupId> <artifactId>prometheus-hystrix</artifactId> <version>4.0.0</version> <exclusions> <exclusion> <artifactId>simpleclient</artifactId> <groupId>io.prometheus</groupId> </exclusion> <exclusion> <artifactId>simpleclient_common</artifactId> <groupId>io.prometheus</groupId> </exclusion> <exclusion> <artifactId>hystrix-core</artifactId> <groupId>com.netflix.hystrix</groupId> </exclusion> </exclusions> </dependency>
二、添加核心类
优化点:
1、自定义并发策略,主要重写了线程池的拒绝策略,默认是直接拒绝(主线程执行并告警)
2、统一了线程池的定义方式以及启动初始化线程池 (这样处理的好处就是简化了使用)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * @Author zhangboqing * @Date 2020/11/17 */ @Configuration @Slf4j public class HystrixCircuitBreakerConfiguration { @Autowired(required = false) private HystrixConcurrencyStrategy existingConcurrencyStrategy; @Autowired CollectorRegistry registry; @Bean public HystrixCommandAspect hystrixCommandAspect() { return new HystrixCommandAspect(); } @Bean public HystrixShutdownHook hystrixShutdownHook() { return new HystrixShutdownHook(); } @Bean DefaultHystrixConcurrencyStrategy defaultHystrixConcurrencyStrategy(Tracing tracing, SpanNamer spanNamer) { return new DefaultHystrixConcurrencyStrategy(tracing, spanNamer); } @PostConstruct public void init() { // Keeps references of existing Hystrix plugins. HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance() .getEventNotifier(); HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance() .getMetricsPublisher(); HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance() .getPropertiesStrategy(); HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins.getInstance() .getCommandExecutionHook(); HystrixConcurrencyStrategy concurrencyStrategy = detectRegisteredConcurrencyStrategy(); HystrixPlugins.reset(); // Registers existing plugins excepts the Concurrent Strategy plugin. HystrixPlugins.getInstance().registerConcurrencyStrategy(concurrencyStrategy); HystrixPlugins.getInstance().registerEventNotifier(eventNotifier); HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher); HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy); HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook); HystrixPrometheusMetricsPublisher.builder().withRegistry(registry).shouldExportProperties(true).buildAndRegister(); // 初始化线程池 initThreadPoolKey(); } private void initThreadPoolKey() { HystrixThreadPoolKeyEnum[] values = HystrixThreadPoolKeyEnum.values(); if (values.length > 0) { Arrays.stream(values).forEach(key->{ new BaseHystrixCommand(key) { @Override protected Object run() throws Exception { return null; } }.execute(); }); } } private HystrixConcurrencyStrategy detectRegisteredConcurrencyStrategy() { HystrixConcurrencyStrategy registeredStrategy = HystrixPlugins.getInstance() .getConcurrencyStrategy(); if (existingConcurrencyStrategy == null) { return registeredStrategy; } // Hystrix registered a default Strategy. if (registeredStrategy instanceof HystrixConcurrencyStrategyDefault) { return existingConcurrencyStrategy; } // If registeredStrategy not the default and not some use bean of // existingConcurrencyStrategy. if (!existingConcurrencyStrategy.equals(registeredStrategy)) { log.warn( "Multiple HystrixConcurrencyStrategy detected. Bean of HystrixConcurrencyStrategy was used."); } return existingConcurrencyStrategy; } /** * {@link DisposableBean} that makes sure that Hystrix internal state is cleared when * {@link ApplicationContext} shuts down. */ private class HystrixShutdownHook implements DisposableBean { @Override public void destroy() throws Exception { // Just call Hystrix to reset thread pool etc. Hystrix.reset(); } } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * @Author zhangboqing * @Date 2020/11/12 */ @Component @Slf4j public class DefaultHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy { @Autowired private PolarisMetricsService polarisMetricsService; @Override public ThreadPoolExecutor getThreadPool(final HystrixThreadPoolKey threadPoolKey, HystrixProperty<Integer> corePoolSize, HystrixProperty<Integer> maximumPoolSize, HystrixProperty<Integer> keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { final ThreadFactory threadFactory = getThreadFactory(threadPoolKey); final int dynamicCoreSize = corePoolSize.get(); final int dynamicMaximumSize = maximumPoolSize.get(); if (dynamicCoreSize > dynamicMaximumSize) { log.error("Hystrix ThreadPool configuration at startup for : " + threadPoolKey.name() + " is trying to set coreSize = " + dynamicCoreSize + " and maximumSize = " + dynamicMaximumSize + ". Maximum size will be set to " + dynamicCoreSize + ", the coreSize value, since it must be equal to or greater than the coreSize value"); return new ThreadPoolExecutor(dynamicCoreSize, dynamicCoreSize, keepAliveTime.get(), unit, workQueue, threadFactory, new DefaultRejectedExecutionHandler(polarisMetricsService,threadPoolKey)); } else { return new ThreadPoolExecutor(dynamicCoreSize, dynamicMaximumSize, keepAliveTime.get(), unit, workQueue, threadFactory, new DefaultRejectedExecutionHandler(polarisMetricsService,threadPoolKey)); } } @Override public ThreadPoolExecutor getThreadPool(final HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties threadPoolProperties) { final ThreadFactory threadFactory = getThreadFactory(threadPoolKey); final boolean allowMaximumSizeToDivergeFromCoreSize = threadPoolProperties.getAllowMaximumSizeToDivergeFromCoreSize().get(); final int dynamicCoreSize = threadPoolProperties.coreSize().get(); final int keepAliveTime = threadPoolProperties.keepAliveTimeMinutes().get(); final int maxQueueSize = threadPoolProperties.maxQueueSize().get(); final BlockingQueue<Runnable> workQueue = getBlockingQueue(maxQueueSize); if (allowMaximumSizeToDivergeFromCoreSize) { final int dynamicMaximumSize = threadPoolProperties.maximumSize().get(); if (dynamicCoreSize > dynamicMaximumSize) { log.error("Hystrix ThreadPool configuration at startup for : " + threadPoolKey.name() + " is trying to set coreSize = " + dynamicCoreSize + " and maximumSize = " + dynamicMaximumSize + ". Maximum size will be set to " + dynamicCoreSize + ", the coreSize value, since it must be equal to or greater than the coreSize value"); return new ThreadPoolExecutor(dynamicCoreSize, dynamicCoreSize, keepAliveTime, TimeUnit.MINUTES, workQueue, threadFactory, new DefaultRejectedExecutionHandler(polarisMetricsService,threadPoolKey)); } else { return new ThreadPoolExecutor(dynamicCoreSize, dynamicMaximumSize, keepAliveTime, TimeUnit.MINUTES, workQueue, threadFactory, new DefaultRejectedExecutionHandler(polarisMetricsService,threadPoolKey)); } } else { return new ThreadPoolExecutor(dynamicCoreSize, dynamicCoreSize, keepAliveTime, TimeUnit.MINUTES, workQueue, threadFactory, new DefaultRejectedExecutionHandler(polarisMetricsService,threadPoolKey)); } } private static ThreadFactory getThreadFactory(final HystrixThreadPoolKey threadPoolKey) { if (!PlatformSpecific.isAppEngineStandardEnvironment()) { return new ThreadFactory() { private final AtomicInteger threadNumber = new AtomicInteger(0); @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r, "hystrix-" + threadPoolKey.name() + "-" + threadNumber.incrementAndGet()); thread.setDaemon(true); return thread; } }; } else { return PlatformSpecific.getAppEngineThreadFactory(); } } public static class DefaultRejectedExecutionHandler implements RejectedExecutionHandler { private PolarisMetricsService polarisMetricsService; private HystrixThreadPoolKey threadPoolKey; public DefaultRejectedExecutionHandler(PolarisMetricsService polarisMetricsService, HystrixThreadPoolKey threadPoolKey) { this.polarisMetricsService = polarisMetricsService; this.threadPoolKey = threadPoolKey; } @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { // 请求阻塞,告警 polarisMetricsService.recordMetrics(PolarisCommonMetricEnum.HYSTRIX_THREAD_POOL_FULL_WARNING.generatePolarisParam("Hystrix Warning", "Hystrix线程池队列已满,请扩容,threadPoolKey:" + threadPoolKey.name())); if (!executor.isShutdown()) { r.run(); } } } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * @Author zhangboqing * @Date 2020/11/17 */ public abstract class BaseHystrixCommand<R> extends HystrixCommand<R> { public BaseHystrixCommand(HystrixThreadPoolKeyEnum threadPoolKeyEnum) { super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(threadPoolKeyEnum.getThreadPoolKey())) /* 使用HystrixThreadPoolKey工厂定义线程池名称*/ .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(threadPoolKeyEnum.getThreadPoolKey())) .andCommandPropertiesDefaults(HystrixCommandProperties.Setter() .withExecutionTimeoutEnabled(threadPoolKeyEnum.getExecutionTimeoutEnabled()) .withExecutionTimeoutInMilliseconds(threadPoolKeyEnum.getExecutionTimeoutInMilliseconds())) .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(threadPoolKeyEnum.getCoreSize()).withMaximumSize(threadPoolKeyEnum.getMaximumSize()).withMaxQueueSize(threadPoolKeyEnum.getMaxQueueSize()).withQueueSizeRejectionThreshold(threadPoolKeyEnum.getMaxQueueSize() + 1))); } public BaseHystrixCommand(HystrixThreadPoolKeyEnum threadPoolKeyEnum,Integer timeoutInMilliseconds) { super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(threadPoolKeyEnum.getThreadPoolKey())) /* 使用HystrixThreadPoolKey工厂定义线程池名称*/ .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(threadPoolKeyEnum.getThreadPoolKey())) .andCommandPropertiesDefaults(HystrixCommandProperties.Setter() .withExecutionTimeoutEnabled(true) .withExecutionTimeoutInMilliseconds(timeoutInMilliseconds)) .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(threadPoolKeyEnum.getCoreSize()).withMaximumSize(threadPoolKeyEnum.getMaximumSize()).withMaxQueueSize(threadPoolKeyEnum.getMaxQueueSize()).withQueueSizeRejectionThreshold(threadPoolKeyEnum.getMaxQueueSize() + 1))); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * @Author zhangboqing * @Date 2020/11/18 */ @SuppressWarnings(value = "all") public class HystrixProperties { // 线程池名称 // 注意,增加新的线程名必须同时在HystrixThreadPoolKeyEnum中也新增一个,保持1对1的关系 public static class ThreadPoolName { public static final String DEFAULT_THREADPOOLKEY = "DEFUALT"; // 默认线程池名称 } // 默认属性 public static final String DEFAULT_EXECUTIONTIMEOUTINMILLISECONDS = "5000"; // 超时时间,单位毫秒 public static final String DEFAULT_EXECUTIONTIMEOUTENABLED = "false"; // 是否允许超时 public static final String DEFAULT_CORESIZE = "20"; // 核心线程数 public static final String DEFAULT_MAXIMUMSIZE = "100"; // 最大线程数 public static final String DEFAULT_KEEPALIVETIMEMINUTES = "1"; // 闲置线程存活时间,单位分钟 public static final String DEFAULT_MAXQUEUESIZE = "500"; // 线程池最大队列大小 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * @Author zhangboqing * @Date 2020/11/18 */ @SuppressWarnings(value = "all") public enum HystrixThreadPoolKeyEnum { DEFAULT_HYSTRIX_THREAD_POOL( String.valueOf(HystrixProperties.ThreadPoolName.DEFAULT_THREADPOOLKEY), Boolean.valueOf(HystrixProperties.DEFAULT_EXECUTIONTIMEOUTENABLED), Integer.valueOf(HystrixProperties.DEFAULT_EXECUTIONTIMEOUTINMILLISECONDS), Integer.valueOf(HystrixProperties.DEFAULT_CORESIZE), Integer.valueOf(HystrixProperties.DEFAULT_MAXIMUMSIZE), Integer.valueOf(HystrixProperties.DEFAULT_KEEPALIVETIMEMINUTES), Integer.valueOf(HystrixProperties.DEFAULT_MAXQUEUESIZE) ); HystrixThreadPoolKeyEnum(String threadPoolKey, Boolean executionTimeoutEnabled, Integer executionTimeoutInMilliseconds, Integer coreSize, Integer maximumSize, Integer keepAliveTimeMinutes, Integer maxQueueSize) { Assert.hasText(threadPoolKey, "threadPoolKey can not empty"); Assert.notNull(executionTimeoutEnabled, "executionTimeoutEnabled can not empty"); Assert.notNull(executionTimeoutInMilliseconds, "executionTimeoutInMilliseconds can not empty"); Assert.notNull(coreSize, "coreSize can not empty"); Assert.notNull(maximumSize, "maximumSize can not empty"); Assert.notNull(keepAliveTimeMinutes, "keepAliveTimeMinutes can not empty"); Assert.notNull(maxQueueSize, "maxQueueSize can not empty"); this.threadPoolKey = threadPoolKey; this.executionTimeoutInMilliseconds = executionTimeoutInMilliseconds; this.coreSize = coreSize; this.maximumSize = maximumSize; this.keepAliveTimeMinutes = keepAliveTimeMinutes; this.maxQueueSize = maxQueueSize; this.executionTimeoutEnabled = executionTimeoutEnabled; } private final String threadPoolKey; // 线程池名称 private final Integer executionTimeoutInMilliseconds; // 超时时间,单位毫秒 private final Boolean executionTimeoutEnabled; // // 是否允许超时 private final Integer coreSize; // 核心线程数 private final Integer maximumSize; // 最大线程数 private final Integer keepAliveTimeMinutes; // 闲置线程存活时间,单位分钟 private final Integer maxQueueSize; // 线程池最大队列大小 public String getThreadPoolKey() { return threadPoolKey; } public Integer getExecutionTimeoutInMilliseconds() { return executionTimeoutInMilliseconds; } public Integer getCoreSize() { return coreSize; } public Integer getMaximumSize() { return maximumSize; } public Integer getKeepAliveTimeMinutes() { return keepAliveTimeMinutes; } public Integer getMaxQueueSize() { return maxQueueSize; } public Boolean getExecutionTimeoutEnabled() { return executionTimeoutEnabled; } }
三、Grafana监控面板配置
![](https://img2020.cnblogs.com/blog/697265/202101/697265-20210131234320197-1370060004.png)
![](https://img2020.cnblogs.com/blog/697265/202101/697265-20210131234348018-563809477.png)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
{ "annotations": { "list": [ { "builtIn": 1, "datasource": "-- Grafana --", "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "type": "dashboard" } ] }, "description": "", "editable": true, "gnetId": 7145, "graphTooltip": 0, "id": 3, "iteration": 1605446629324, "links": [], "panels": [ { "collapsed": false, "datasource": null, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 21, "panels": [], "title": "Command", "type": "row" }, { "aliasColors": {}, "bars": false, "cacheTimeout": null, "dashLength": 10, "dashes": false, "datasource": "Prometheus", "fieldConfig": { "defaults": { "custom": {}, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] } }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 24, "x": 0, "y": 1 }, "hiddenSeries": false, "hideTimeOverride": true, "id": 2, "interval": null, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "links": [], "maxDataPoints": 100, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "7.3.2", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "sum(increase({__name__=~\"hystrix_command_event_total\",command_group=~\"$commandGroup\",command_name=~\"$commandName\",job=~\"$service\",instance=~\"$instance\"}[5m])) by (event)", "format": "time_series", "hide": false, "instant": false, "interval": "", "intervalFactor": 1, "legendFormat": "{{event}}", "metric": "ml_hystrix_command_is_circuit_breaker_open", "refId": "A", "step": 1 }, { "expr": "sum(increase({__name__=~\"hystrix_command_event_total\",event=\"fallback_success\",command_group=~\"$commandGroup\",command_name=~\"$commandName\",job=~\"$service\",instance=~\"$instance\"}[5m])) by (event)", "hide": true, "interval": "", "legendFormat": "", "refId": "B" }, { "expr": "sum(increase({__name__=~\"hystrix_command_event_total\",event=\"fallback_failure\",command_group=~\"$commandGroup\",command_name=~\"$commandName\",job=~\"$service\",instance=~\"$instance\"}[5m])) by (event)", "hide": true, "interval": "", "legendFormat": "", "refId": "C" }, { "expr": "sum(increase({__name__=~\"hystrix_command_event_total\",event=\"fallback_missing\",command_group=~\"$commandGroup\",command_name=~\"$commandName\",job=~\"$service\",instance=~\"$instance\"}[5m])) by (event)", "hide": true, "interval": "", "legendFormat": "", "refId": "D" }, { "expr": "sum(increase({__name__=~\"hystrix_command_event_total\",terminal=\"true\",command_group=~\"$commandGroup\",command_name=~\"$commandName\",job=~\"$service\",instance=~\"$instance\"}[5m])) by (event)", "hide": true, "interval": "", "legendFormat": "", "refId": "E" } ], "thresholds": [], "timeFrom": "15s", "timeRegions": [], "timeShift": null, "title": "Event Statistics", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": null, "description": "", "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 9 }, "hiddenSeries": false, "id": 23, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "7.3.2", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "hystrix_command_is_circuit_breaker_open{command_group=~\"$commandGroup\",command_name=~\"$commandName\",job=~\"$service\",instance=~\"$instance\"}", "interval": "", "legendFormat": "{{command_group}}--{{command_name}}", "refId": "A" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "断路器状态", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": null, "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 9 }, "hiddenSeries": false, "id": 25, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "7.3.2", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "hystrix_command_execution_semaphore_permits_in_use{command_group=~\"$commandGroup\",command_name=~\"$commandName\",job=~\"$service\",instance=~\"$instance\"}", "interval": "", "legendFormat": "{{command_group}}--{{command_name}}", "refId": "A" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "并发执行统计", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": null, "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 17 }, "hiddenSeries": false, "id": 27, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "7.3.2", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "sum by(command_group,command_name) (irate(hystrix_command_latency_total_seconds_count{command_group=~\"$commandGroup\",command_name=~\"$commandName\",job=~\"$service\",instance=~\"$instance\"}[5m]))", "interval": "", "legendFormat": "{{command_group}}--{{command_name}}", "refId": "A" }, { "expr": "sum(irate(hystrix_command_latency_total_seconds_count{command_group=~\"$commandGroup\",command_name=~\"$commandName\",job=~\"$service\",instance=~\"$instance\"}[5m]))", "interval": "", "legendFormat": "qps", "refId": "B" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "命令执行次数统计", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": null, "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 17 }, "hiddenSeries": false, "id": 29, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "7.3.2", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "sum by (command_group,command_name)(irate(hystrix_command_latency_total_seconds_sum{command_group=~\"$commandGroup\",command_name=~\"$commandName\",job=~\"$service\",instance=~\"$instance\"}[5m])) / sum by (command_group,command_name)(irate(hystrix_command_latency_execute_seconds_count{command_group=~\"$commandGroup\",command_name=~\"$commandName\",job=~\"$service\",instance=~\"$instance\"}[5m])) ", "interval": "", "legendFormat": "{{command_group}}--{{command_name}}", "refId": "A" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "命令执行时间统计", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": null, "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 25 }, "hiddenSeries": false, "id": 31, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "7.3.2", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "irate(hystrix_command_error_total{command_group=~\"$commandGroup\",command_name=~\"$commandName\",job=~\"$service\",instance=~\"$instance\"}[5m])", "interval": "", "legendFormat": "{{command_group}}--{{command_name}}", "refId": "A" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "命令失败统计", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": null, "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 25 }, "hiddenSeries": false, "id": 33, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "7.3.2", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "irate(hystrix_command_total{command_group=~\"$commandGroup\",command_name=~\"$commandName\",job=~\"$service\",instance=~\"$instance\"}[5m])", "interval": "", "legendFormat": "{{command_group}}--{{command_name}}", "refId": "A" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "命令成功统计", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "collapsed": false, "datasource": null, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 33 }, "id": 19, "panels": [], "title": "Thread", "type": "row" }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": null, "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 34 }, "hiddenSeries": false, "id": 35, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "7.3.2", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "hystrix_thread_pool_thread_active_count{pool_name=~\"$pool_name\",job=~\"$service\",instance=~\"$instance\"}", "hide": true, "interval": "", "legendFormat": "{{pool_name}}【active】", "refId": "A" }, { "expr": "hystrix_thread_pool_property_value_core_pool_size{pool_name=~\"$pool_name\",job=~\"$service\",instance=~\"$instance\"}-hystrix_thread_pool_thread_active_count{pool_name=~\"$pool_name\",job=~\"$service\",instance=~\"$instance\"}", "interval": "", "legendFormat": "{{pool_name}}【idle】", "refId": "B" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "空闲线程数", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": null, "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 34 }, "hiddenSeries": false, "id": 37, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "7.3.2", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "hystrix_thread_pool_queue_size{pool_name=~\"$pool_name\",job=~\"$service\",instance=~\"$instance\"}", "hide": true, "interval": "", "legendFormat": "{{pool_name}}【used】", "refId": "A" }, { "expr": "hystrix_thread_pool_property_value_queue_size_rejection_threshold{pool_name=~\"$pool_name\",job=~\"$service\",instance=~\"$instance\"}-hystrix_thread_pool_queue_size{pool_name=~\"$pool_name\",job=~\"$service\",instance=~\"$instance\"}", "interval": "", "legendFormat": "{{pool_name}}【idle】", "refId": "B" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "剩余队列大小", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } } ], "refresh": "5s", "schemaVersion": 26, "style": "dark", "tags": [], "templating": { "list": [ { "allValue": null, "current": { "selected": false, "text": "All", "value": "$__all" }, "datasource": "Prometheus", "definition": "", "error": null, "hide": 0, "includeAll": true, "label": "Service", "multi": true, "name": "service", "options": [], "query": "label_values(job)", "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 0, "tagValuesQuery": "", "tags": [], "tagsQuery": "", "type": "query", "useTags": false }, { "allValue": null, "current": { "selected": true, "text": [ "All" ], "value": [ "$__all" ] }, "datasource": "Prometheus", "definition": "query_result({job=~\"$service\"})", "error": null, "hide": 0, "includeAll": true, "label": "Instance", "multi": true, "name": "instance", "options": [], "query": "query_result({job=~\"$service\"})", "refresh": 1, "regex": "/instance=\"(.*?)\".*/", "skipUrlSync": false, "sort": 0, "tagValuesQuery": "", "tags": [], "tagsQuery": "", "type": "query", "useTags": false }, { "allValue": null, "current": { "selected": true, "text": [ "All" ], "value": [ "$__all" ] }, "datasource": "Prometheus", "definition": "query_result({job=~\"$service\",instance=~\"$instance\"})", "error": null, "hide": 0, "includeAll": true, "label": "Command Group", "multi": true, "name": "commandGroup", "options": [], "query": "query_result({job=~\"$service\",instance=~\"$instance\"})", "refresh": 1, "regex": "/command_group=\"(.*?)\".*/", "skipUrlSync": false, "sort": 0, "tagValuesQuery": "", "tags": [], "tagsQuery": "", "type": "query", "useTags": false }, { "allValue": null, "current": { "selected": false, "text": "All", "value": "$__all" }, "datasource": "Prometheus", "definition": "query_result({job=~\"$service\",instance=~\"$instance\",command_group=~\"$commandGroup\"})", "error": null, "hide": 0, "includeAll": true, "label": "Command Name", "multi": true, "name": "commandName", "options": [], "query": "query_result({job=~\"$service\",instance=~\"$instance\",command_group=~\"$commandGroup\"})", "refresh": 1, "regex": "/command_name=\"(.*?)\".*/", "skipUrlSync": false, "sort": 0, "tagValuesQuery": "", "tags": [], "tagsQuery": "", "type": "query", "useTags": false }, { "allValue": null, "current": { "selected": false, "text": "All", "value": "$__all" }, "datasource": "Prometheus", "definition": "query_result({job=~\"$service\",instance=~\"$instance\"})", "error": null, "hide": 0, "includeAll": true, "label": "Pool_Name", "multi": true, "name": "pool_name", "options": [], "query": "query_result({job=~\"$service\",instance=~\"$instance\"})", "refresh": 1, "regex": "/pool_name=\"(.*?)\".*/", "skipUrlSync": false, "sort": 0, "tagValuesQuery": "", "tags": [], "tagsQuery": "", "type": "query", "useTags": false } ] }, "time": { "from": "now-5m", "to": "now" }, "timepicker": { "refresh_intervals": [ "5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d" ], "time_options": [ "5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d" ] }, "timezone": "browser", "title": "Custom Hystrix Dashboard", "uid": "DqrjMNKik", "version": 19 }
四、使用Demo
1)代码方式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * @Author zhangboqing * @Date 2020/11/18 * 命令方式 */ @Slf4j @Builder public class TestHystrixCommand extends BaseHystrixCommand<String> { String value; public TestHystrixCommand(String value) { super(HystrixThreadPoolKeyEnum.DEFAULT_HYSTRIX_THREAD_POOL); this.value = value; } @Override protected String run() throws Exception { log.info("invoke"); return value; } // 实现降级逻辑(发生超时或异常执行) @Override protected String getFallback() { return "getFallback"; } public static void main(String[] args) throws ExecutionException, InterruptedException { // 同步调用 String execute = TestHystrixCommand.builder().value("212").build().execute(); log.info("result:{}",execute); // 异步调用 // 关注结果 Future<String> future = TestHystrixCommand.builder().value("212").build().queue(); log.info("result:{}",future.get()); // 不关注结果 TestHystrixCommand.builder().value("212").build().observe().subscribe(); } }
2)注解方式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * @Author zhangboqing * @Date 2020/11/18 * 注解方式 */ @Service @Slf4j public class TestHystrixAnnotation { /** * 同步 */ // 不设置超时 @HystrixCommand( groupKey = HystrixProperties.ThreadPoolName.DEFAULT_THREADPOOLKEY, commandProperties = { @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_TIMEOUT_ENABLED, value = HystrixProperties.DEFAULT_EXECUTIONTIMEOUTENABLED) }, fallbackMethod = "runFallback" ) public Object run() { int a = 1 / 0; log.info(">>>>>>> execute run"); return "run"; } // 设置超时 @HystrixCommand( groupKey = HystrixProperties.ThreadPoolName.DEFAULT_THREADPOOLKEY, commandProperties = { @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_THREAD_TIMEOUT_IN_MILLISECONDS, value = HystrixProperties.DEFAULT_EXECUTIONTIMEOUTINMILLISECONDS) }, fallbackMethod = "runFallback" ) public Object run2() { log.info(">>>>>>> execute run"); return "run"; } public String runFallback() { return "runFallback"; } @HystrixCommand( groupKey = HystrixProperties.ThreadPoolName.DEFAULT_THREADPOOLKEY, commandProperties = { @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_TIMEOUT_ENABLED, value = HystrixProperties.DEFAULT_EXECUTIONTIMEOUTENABLED) } ) public Object run3() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } log.info(">>>>>>> execute run3"); return "run"; } /** * 异步 */ @HystrixCommand( groupKey = HystrixProperties.ThreadPoolName.DEFAULT_THREADPOOLKEY, commandProperties = { @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_TIMEOUT_ENABLED, value = HystrixProperties.DEFAULT_EXECUTIONTIMEOUTENABLED) } ) public Future<String> run4() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } log.info(">>>>>>> execute run4"); return new AsyncResult<String>() { @Override public String invoke() { return "run4"; } }; } }
你投入得越多,就能得到越多得价值