Hystrix的使用

Posted Dreamer who

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hystrix的使用相关的知识,希望对你有一定的参考价值。

Hystrix虽然已经停止更新迭代,进入了维护阶段,替代品Resilience4j成为了首先,但是遗留系统还有必要维护更新的。

Hystrix在项目中经常使用的方式主要有三种方式在;

1、继承HystrixCommand实现代理类,把之前的业务逻辑写在run()方法内

 

代码示例详见:https://github.com/Netflix/Hystrix/wiki/How-To-Use

而且支持同步执行、异步执行(返回Future)及响应式编程方式执行(返回Observable)。

 

2、使用注解@HystrixCommand,aop方式

 

这种适用于大量的方法需要熔断处理,官方给了封装的类库:https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica,aop方式比较简单,省去了大量的重复性的代码量。

spring cloud环境下会帮我们自动配置:

 

 

3、feign 结合Hystrix

 

如果使用spring cloud微服务栈的话,feign是一般要使用的,所以feign自带了组件:https://github.com/OpenFeign/feign/tree/master/hystrix

当然为了性能feign也支持异步返回。返回的对象支持:HystrixCommand<T>、Observable<T>、Single<T>、

CompletableFuture<T>、T。

具体可以看源码:feign.hystrix.HystrixInvocationHandler 的实现:

 

 

使用了Hystrix,很多配置https://github.com/Netflix/Hystrix/wiki/Configuration 不一定适合业务,所以需要动态的监控这些配置并实时的调整配置(注意有些配置更新了也起不了效果)。

根据源码com.netflix.hystrix.contrib.javanica.conf.HystrixPropertiesManager#setProperties的描述:

 

ConfigurationManager.getConfigInstance().setProperty(propName, property.getValue()); 工具类可以动态更新配置。

例如https://github.com/Netflix/Hystrix/wiki/Configuration#ThreadPool的设置key有:

一般我们设置实例的属性:hystrix.threadpool.HystrixThreadPoolKey.coreSize,HystrixThreadPoolKey是我们

 

.andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(HYSTRIXT_HREAD_POOLKEY)) 设置的实例线程池key的名字。

 

各种指标监控的数据通过HystrixCommandMetrics、HystrixThreadPoolMetrics来获取,可以看个源码实例:

https://github.com/Netflix/Hystrix/blob/master/hystrix-contrib/hystrix-metrics-event-stream/src/main/java/com/netflix/hystrix/contrib/metrics/eventstream/HystrixMetricsPoller.java

 

 for (HystrixCommandMetrics commandMetrics : HystrixCommandMetrics.getInstances()) 
                    HystrixCommandKey key = commandMetrics.getCommandKey();
                    HystrixCircuitBreaker circuitBreaker = HystrixCircuitBreaker.Factory.getInstance(key);

                    StringWriter jsonString = new StringWriter();
                    JsonGenerator json = jsonFactory.createJsonGenerator(jsonString);

                    json.writeStartObject();
                    json.writeStringField("type", "HystrixCommand");
                    json.writeStringField("name", key.name());
                    json.writeStringField("group", commandMetrics.getCommandGroup().name());
                    json.writeNumberField("currentTime", System.currentTimeMillis());

                    // circuit breaker
                    if (circuitBreaker == null) 
                        // circuit breaker is disabled and thus never open
                        json.writeBooleanField("isCircuitBreakerOpen", false);
                     else 
                        json.writeBooleanField("isCircuitBreakerOpen", circuitBreaker.isOpen());
                    
                    HealthCounts healthCounts = commandMetrics.getHealthCounts();
                    json.writeNumberField("errorPercentage", healthCounts.getErrorPercentage());
                    json.writeNumberField("errorCount", healthCounts.getErrorCount());
                    json.writeNumberField("requestCount", healthCounts.getTotalRequests());

                    // rolling counters
                    json.writeNumberField("rollingCountCollapsedRequests", commandMetrics.getRollingCount(HystrixRollingNumberEvent.COLLAPSED));
                    json.writeNumberField("rollingCountExceptionsThrown", commandMetrics.getRollingCount(HystrixRollingNumberEvent.EXCEPTION_THROWN));
                    json.writeNumberField("rollingCountFailure", commandMetrics.getRollingCount(HystrixRollingNumberEvent.FAILURE));
                    json.writeNumberField("rollingCountFallbackFailure", commandMetrics.getRollingCount(HystrixRollingNumberEvent.FALLBACK_FAILURE));
                    json.writeNumberField("rollingCountFallbackRejection", commandMetrics.getRollingCount(HystrixRollingNumberEvent.FALLBACK_REJECTION));
                    json.writeNumberField("rollingCountFallbackSuccess", commandMetrics.getRollingCount(HystrixRollingNumberEvent.FALLBACK_SUCCESS));
                    json.writeNumberField("rollingCountResponsesFromCache", commandMetrics.getRollingCount(HystrixRollingNumberEvent.RESPONSE_FROM_CACHE));
                    json.writeNumberField("rollingCountSemaphoreRejected", commandMetrics.getRollingCount(HystrixRollingNumberEvent.SEMAPHORE_REJECTED));
                    json.writeNumberField("rollingCountShortCircuited", commandMetrics.getRollingCount(HystrixRollingNumberEvent.SHORT_CIRCUITED));
                    json.writeNumberField("rollingCountSuccess", commandMetrics.getRollingCount(HystrixRollingNumberEvent.SUCCESS));
                    json.writeNumberField("rollingCountThreadPoolRejected", commandMetrics.getRollingCount(HystrixRollingNumberEvent.THREAD_POOL_REJECTED));
                    json.writeNumberField("rollingCountTimeout", commandMetrics.getRollingCount(HystrixRollingNumberEvent.TIMEOUT));

                    json.writeNumberField("currentConcurrentExecutionCount", commandMetrics.getCurrentConcurrentExecutionCount());

                    // latency percentiles
                    json.writeNumberField("latencyExecute_mean", commandMetrics.getExecutionTimeMean());
                    json.writeObjectFieldStart("latencyExecute");
                    json.writeNumberField("0", commandMetrics.getExecutionTimePercentile(0));
                    json.writeNumberField("25", commandMetrics.getExecutionTimePercentile(25));
                    json.writeNumberField("50", commandMetrics.getExecutionTimePercentile(50));
                    json.writeNumberField("75", commandMetrics.getExecutionTimePercentile(75));
                    json.writeNumberField("90", commandMetrics.getExecutionTimePercentile(90));
                    json.writeNumberField("95", commandMetrics.getExecutionTimePercentile(95));
                    json.writeNumberField("99", commandMetrics.getExecutionTimePercentile(99));
                    json.writeNumberField("99.5", commandMetrics.getExecutionTimePercentile(99.5));
                    json.writeNumberField("100", commandMetrics.getExecutionTimePercentile(100));
                    json.writeEndObject();
                    //
                    json.writeNumberField("latencyTotal_mean", commandMetrics.getTotalTimeMean());
                    json.writeObjectFieldStart("latencyTotal");
                    json.writeNumberField("0", commandMetrics.getTotalTimePercentile(0));
                    json.writeNumberField("25", commandMetrics.getTotalTimePercentile(25));
                    json.writeNumberField("50", commandMetrics.getTotalTimePercentile(50));
                    json.writeNumberField("75", commandMetrics.getTotalTimePercentile(75));
                    json.writeNumberField("90", commandMetrics.getTotalTimePercentile(90));
                    json.writeNumberField("95", commandMetrics.getTotalTimePercentile(95));
                    json.writeNumberField("99", commandMetrics.getTotalTimePercentile(99));
                    json.writeNumberField("99.5", commandMetrics.getTotalTimePercentile(99.5));
                    json.writeNumberField("100", commandMetrics.getTotalTimePercentile(100));
                    json.writeEndObject();

                    // property values for reporting what is actually seen by the command rather than what was set somewhere
                    HystrixCommandProperties commandProperties = commandMetrics.getProperties();

                    json.writeNumberField("propertyValue_circuitBreakerRequestVolumeThreshold", commandProperties.circuitBreakerRequestVolumeThreshold().get());
                    json.writeNumberField("propertyValue_circuitBreakerSleepWindowInMilliseconds", commandProperties.circuitBreakerSleepWindowInMilliseconds().get());
                    json.writeNumberField("propertyValue_circuitBreakerErrorThresholdPercentage", commandProperties.circuitBreakerErrorThresholdPercentage().get());
                    json.writeBooleanField("propertyValue_circuitBreakerForceOpen", commandProperties.circuitBreakerForceOpen().get());
                    json.writeBooleanField("propertyValue_circuitBreakerForceClosed", commandProperties.circuitBreakerForceClosed().get());
                    json.writeBooleanField("propertyValue_circuitBreakerEnabled", commandProperties.circuitBreakerEnabled().get());

                    json.writeStringField("propertyValue_executionIsolationStrategy", commandProperties.executionIsolationStrategy().get().name());
                    json.writeNumberField("propertyValue_executionIsolationThreadTimeoutInMilliseconds", commandProperties.executionIsolationThreadTimeoutInMilliseconds().get());
                    json.writeBooleanField("propertyValue_executionIsolationThreadInterruptOnTimeout", commandProperties.executionIsolationThreadInterruptOnTimeout().get());
                    json.writeStringField("propertyValue_executionIsolationThreadPoolKeyOverride", commandProperties.executionIsolationThreadPoolKeyOverride().get());
                    json.writeNumberField("propertyValue_executionIsolationSemaphoreMaxConcurrentRequests", commandProperties.executionIsolationSemaphoreMaxConcurrentRequests().get());
                    json.writeNumberField("propertyValue_fallbackIsolationSemaphoreMaxConcurrentRequests", commandProperties.fallbackIsolationSemaphoreMaxConcurrentRequests().get());

                    /*
                     * The following are commented out as these rarely change and are verbose for streaming for something people don't change.
                     * We could perhaps allow a property or request argument to include these.
                     */

                    //                    json.put("propertyValue_metricsRollingPercentileEnabled", commandProperties.metricsRollingPercentileEnabled().get());
                    //                    json.put("propertyValue_metricsRollingPercentileBucketSize", commandProperties.metricsRollingPercentileBucketSize().get());
                    //                    json.put("propertyValue_metricsRollingPercentileWindow", commandProperties.metricsRollingPercentileWindowInMilliseconds().get());
                    //                    json.put("propertyValue_metricsRollingPercentileWindowBuckets", commandProperties.metricsRollingPercentileWindowBuckets().get());
                    //                    json.put("propertyValue_metricsRollingStatisticalWindowBuckets", commandProperties.metricsRollingStatisticalWindowBuckets().get());
                    json.writeNumberField("propertyValue_metricsRollingStatisticalWindowInMilliseconds", commandProperties.metricsRollingStatisticalWindowInMilliseconds().get());

                    json.writeBooleanField("propertyValue_requestCacheEnabled", commandProperties.requestCacheEnabled().get());
                    json.writeBooleanField("propertyValue_requestLogEnabled", commandProperties.requestLogEnabled().get());

                    json.writeNumberField("reportingHosts", 1); // this will get summed across all instances in a cluster

                    json.writeEndObject();
                    json.close();

                    // output to handler
                    listener.handleJsonMetric(jsonString.getBuffer().toString());
                

                // thread pool metrics
                for (HystrixThreadPoolMetrics threadPoolMetrics : HystrixThreadPoolMetrics.getInstances()) 
                    HystrixThreadPoolKey key = threadPoolMetrics.getThreadPoolKey();

                    StringWriter jsonString = new StringWriter();
                    JsonGenerator json = jsonFactory.createJsonGenerator(jsonString);
                    json.writeStartObject();

                    json.writeStringField("type", "HystrixThreadPool");
                    json.writeStringField("name", key.name());
                    json.writeNumberField("currentTime", System.currentTimeMillis());

                    json.writeNumberField("currentActiveCount", threadPoolMetrics.getCurrentActiveCount().intValue());
                    json.writeNumberField("currentCompletedTaskCount", threadPoolMetrics.getCurrentCompletedTaskCount().longValue());
                    json.writeNumberField("currentCorePoolSize", threadPoolMetrics.getCurrentCorePoolSize().intValue());
                    json.writeNumberField("currentLargestPoolSize", threadPoolMetrics.getCurrentLargestPoolSize().intValue());
                    json.writeNumberField("currentMaximumPoolSize", threadPoolMetrics.getCurrentMaximumPoolSize().intValue());
                    json.writeNumberField("currentPoolSize", threadPoolMetrics.getCurrentPoolSize().intValue());
                    json.writeNumberField("currentQueueSize", threadPoolMetrics.getCurrentQueueSize().intValue());
                    json.writeNumberField("currentTaskCount", threadPoolMetrics.getCurrentTaskCount().longValue());
                    json.writeNumberField("rollingCountThreadsExecuted", threadPoolMetrics.getRollingCountThreadsExecuted());
                    json.writeNumberField("rollingMaxActiveThreads", threadPoolMetrics.getRollingMaxActiveThreads());

                    json.writeNumberField("propertyValue_queueSizeRejectionThreshold", threadPoolMetrics.getProperties().queueSizeRejectionThreshold().get());
                    json.writeNumberField("propertyValue_metricsRollingStatisticalWindowInMilliseconds", threadPoolMetrics.getProperties().metricsRollingStatisticalWindowInMilliseconds().get());

                    json.writeNumberField("reportingHosts", 1); // this will get summed across all instances in a cluster
                    
                    json.writeEndObject();
                    json.close();
                    // output to stream
                    listener.handleJsonMetric(jsonString.getBuffer().toString());
                

 

 

数据的展示如:https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-metrics-event-stream

 

以上是关于Hystrix的使用的主要内容,如果未能解决你的问题,请参考以下文章

继续调用第 3 方,直到它返回 Hystrix 的预期响应

SpringCloud(Hoxton.SR3)基础篇:第五章Hystrix-request collapsing(请求合并)

什么是Hystrix,Hystrix如何使用

hystrix进阶-注解hystrix-javanica使用

springCloud(12):使用Hystrix实现微服务的容错处理-Hystrix的监控

如何使用 hystrix 定义重试次数