hystrix通过rxjava消息模式来获取和监听命令的metrics信息。
metrics主体结构包括一下部分:
hystrix metrics主要分为三个部分,命令执行metrics,线程池metrics,合并命令metrics。分别来统计命令执行过程中产生的metrics,线程池执行过程中产生的metrics,合并命令执行过程汇总产生的metrics。各个metrics内部有两类消息流组件,当各个行为发生时,首先向消息接收流组件发生消息,各类消息分析流组件监听消息接收流组件,对接收到的数据进行统计输出。各个metrics组件再通过监听消息分析流组件来获取统计后的消息。
单例模式
三个metrics都使用了单利模式,以HystrixCommandMetrics为例,key为commandkey。
// String is HystrixCommandKey.name() (we can't use HystrixCommandKey directly as we can't guarantee it implements hashcode/equals correctly) private static final ConcurrentHashMap<String, HystrixCommandMetrics> metrics = new ConcurrentHashMap<String, HystrixCommandMetrics>(); public static HystrixCommandMetrics getInstance(HystrixCommandKey key, HystrixCommandGroupKey commandGroup, HystrixThreadPoolKey threadPoolKey, HystrixCommandProperties properties) { // attempt to retrieve from cache first HystrixCommandMetrics commandMetrics = metrics.get(key.name()); if (commandMetrics != null) { return commandMetrics; } else { synchronized (HystrixCommandMetrics.class) { HystrixCommandMetrics existingMetrics = metrics.get(key.name()); if (existingMetrics != null) { return existingMetrics; } else { HystrixThreadPoolKey nonNullThreadPoolKey; if (threadPoolKey == null) { nonNullThreadPoolKey = HystrixThreadPoolKey.Factory.asKey(commandGroup.name()); } else { nonNullThreadPoolKey = threadPoolKey; } HystrixCommandMetrics newCommandMetrics = new HystrixCommandMetrics(key, commandGroup, nonNullThreadPoolKey, properties, HystrixPlugins.getInstance().getEventNotifier()); metrics.putIfAbsent(key.name(), newCommandMetrics); return newCommandMetrics; } } } }
HystrixCommandMetrics
markCommandStart在命令执行前调用,最终会向开始消息流(HystrixCommandStartStream)发送开始消息(HystrixCommandExecutionStarted)。
markCommandDone在命令执行后调用,最终会向完成消息流(HystrixCommandCompletionStream)发送完成消息(HystrixCommandCompletion)。
/* package-private */ void markCommandStart(HystrixCommandKey commandKey, HystrixThreadPoolKey threadPoolKey, HystrixCommandProperties.ExecutionIsolationStrategy isolationStrategy) { int currentCount = concurrentExecutionCount.incrementAndGet(); HystrixThreadEventStream.getInstance().commandExecutionStarted(commandKey, threadPoolKey, isolationStrategy, currentCount); } /* package-private */ void markCommandDone(ExecutionResult executionResult, HystrixCommandKey commandKey, HystrixThreadPoolKey threadPoolKey, boolean executionStarted) { HystrixThreadEventStream.getInstance().executionDone(executionResult, commandKey, threadPoolKey); if (executionStarted) { concurrentExecutionCount.decrementAndGet(); } }
还有一些统计流,监听了 HystrixCommandStartStream和HystrixCommandCompletionStream进行统计,HystrixCommandMetrics通过这些统计流获得相应的统计数据。
private HealthCountsStream healthCountsStream; private final RollingCommandEventCounterStream rollingCommandEventCounterStream; private final CumulativeCommandEventCounterStream cumulativeCommandEventCounterStream; private final RollingCommandLatencyDistributionStream rollingCommandLatencyDistributionStream; private final RollingCommandUserLatencyDistributionStream rollingCommandUserLatencyDistributionStream; private final RollingCommandMaxConcurrencyStream rollingCommandMaxConcurrencyStream; /* package */HystrixCommandMetrics(final HystrixCommandKey key, HystrixCommandGroupKey commandGroup, HystrixThreadPoolKey threadPoolKey, HystrixCommandProperties properties, HystrixEventNotifier eventNotifier) { super(null); healthCountsStream = HealthCountsStream.getInstance(key, properties); rollingCommandEventCounterStream = RollingCommandEventCounterStream.getInstance(key, properties); cumulativeCommandEventCounterStream = CumulativeCommandEventCounterStream.getInstance(key, properties); rollingCommandLatencyDistributionStream = RollingCommandLatencyDistributionStream.getInstance(key, properties); rollingCommandUserLatencyDistributionStream = RollingCommandUserLatencyDistributionStream.getInstance(key, properties); rollingCommandMaxConcurrencyStream = RollingCommandMaxConcurrencyStream.getInstance(key, properties); } //获取指定事件窗口期内数据指标 public long getRollingCount(HystrixEventType eventType) { return rollingCommandEventCounterStream.getLatest(eventType); } //获取指定事件持续的数据指标 public long getCumulativeCount(HystrixEventType eventType) { return cumulativeCommandEventCounterStream.getLatest(eventType); }//获取某一百分比的执行时间public int getExecutionTimePercentile(double percentile) { return rollingCommandLatencyDistributionStream.getLatestPercentile(percentile); }//获取平均的执行时间 public int getExecutionTimeMean() { return rollingCommandLatencyDistributionStream.getLatestMean(); } //获取某一百分比的总时间 public int getTotalTimePercentile(double percentile) { return rollingCommandUserLatencyDistributionStream.getLatestPercentile(percentile); }//获取平均的总时间 public int getTotalTimeMean() { return rollingCommandUserLatencyDistributionStream.getLatestMean(); } //获取窗口期内最大并发量 public long getRollingMaxConcurrentExecutions() { return rollingCommandMaxConcurrencyStream.getLatestRollingMax(); }//获取当前并发量 public int getCurrentConcurrentExecutionCount() { return concurrentExecutionCount.get(); } //获取命令执行健康情况 public HealthCounts getHealthCounts() { return healthCountsStream.getLatest(); }
HystrixCollapserMetrics
markResponseFromCache、markBatch,最终会向Collapser消息流(HystrixCollapserEventStream)发送Collapser消息(HystrixCollapserEvent)。
public void markResponseFromCache() { HystrixThreadEventStream.getInstance().collapserResponseFromCache(collapserKey); } public void markBatch(int batchSize) { HystrixThreadEventStream.getInstance().collapserBatchExecuted(collapserKey, batchSize); }
还有一些统计流,监听了 HystrixCollapserEventStream进行统计,HystrixCollapserMetrics通过这些统计流获得相应的统计数据。
private final RollingCollapserEventCounterStream rollingCollapserEventCounterStream; private final CumulativeCollapserEventCounterStream cumulativeCollapserEventCounterStream; private final RollingCollapserBatchSizeDistributionStream rollingCollapserBatchSizeDistributionStream; /* package */HystrixCollapserMetrics(HystrixCollapserKey key, HystrixCollapserProperties properties) { super(null); rollingCollapserEventCounterStream = RollingCollapserEventCounterStream.getInstance(key, properties); cumulativeCollapserEventCounterStream = CumulativeCollapserEventCounterStream.getInstance(key, properties); rollingCollapserBatchSizeDistributionStream = RollingCollapserBatchSizeDistributionStream.getInstance(key, properties); } //获取指定事件窗口期内数据指标 public long getRollingCount(HystrixEventType.Collapser collapserEventType) { return rollingCollapserEventCounterStream.getLatest(collapserEventType); } //获取指定事件持续的数据指标 public long getCumulativeCount(HystrixEventType.Collapser collapserEventType) { return cumulativeCollapserEventCounterStream.getLatest(collapserEventType); } //获取指定百分比的batchsize public int getBatchSizePercentile(double percentile) { return rollingCollapserBatchSizeDistributionStream.getLatestPercentile(percentile); } //获取平均的batchsize public int getBatchSizeMean() { return rollingCollapserBatchSizeDistributionStream.getLatestMean(); }
HystrixThreadPoolMetrics
有一些统计流,监听了监听了 HystrixThreadPoolStartStream和HystrixThreadPoolCompletionStream进行统计,HystrixThreadPoolMetrics通过这些统计流获得相应的统计数据。
private final RollingThreadPoolEventCounterStream rollingCounterStream; private final CumulativeThreadPoolEventCounterStream cumulativeCounterStream; private final RollingThreadPoolMaxConcurrencyStream rollingThreadPoolMaxConcurrencyStream; private HystrixThreadPoolMetrics(HystrixThreadPoolKey threadPoolKey, ThreadPoolExecutor threadPool, HystrixThreadPoolProperties properties) { super(null); this.threadPoolKey = threadPoolKey; this.threadPool = threadPool; this.properties = properties; rollingCounterStream = RollingThreadPoolEventCounterStream.getInstance(threadPoolKey, properties); cumulativeCounterStream = CumulativeThreadPoolEventCounterStream.getInstance(threadPoolKey, properties); rollingThreadPoolMaxConcurrencyStream = RollingThreadPoolMaxConcurrencyStream.getInstance(threadPoolKey, properties); } /** 获取窗口期内线程池执行的个数*/ public long getRollingCountThreadsExecuted() { return rollingCounterStream.getLatestCount(HystrixEventType.ThreadPool.EXECUTED); } /** 获取持续的线程池执行个数*/ public long getCumulativeCountThreadsExecuted() { return cumulativeCounterStream.getLatestCount(HystrixEventType.ThreadPool.EXECUTED); } /** 获取窗口期内线程池拒绝的个数*/ public long getRollingCountThreadsRejected() { return rollingCounterStream.getLatestCount(HystrixEventType.ThreadPool.REJECTED); } /** 获取持续内线程池拒绝的个数*/ public long getCumulativeCountThreadsRejected() { return cumulativeCounterStream.getLatestCount(HystrixEventType.ThreadPool.REJECTED); } //获取指定事件窗口期内数据指标 public long getRollingCount(HystrixEventType.ThreadPool event) { return rollingCounterStream.getLatestCount(event); } //获取指定事件持续的数据指标 public long getCumulativeCount(HystrixEventType.ThreadPool event) { return cumulativeCounterStream.getLatestCount(event); }/** 获取窗口期内最大并发量*/ public long getRollingMaxActiveThreads() { return rollingThreadPoolMaxConcurrencyStream.getLatestRollingMax(); }
还有一些根据线程池获取线程池当前指标
public Number getCurrentActiveCount() { return threadPool.getActiveCount(); } public Number getCurrentCompletedTaskCount() { return threadPool.getCompletedTaskCount(); } public Number getCurrentCorePoolSize() { return threadPool.getCorePoolSize(); } public Number getCurrentLargestPoolSize() { return threadPool.getLargestPoolSize(); } public Number getCurrentMaximumPoolSize() { return threadPool.getMaximumPoolSize(); } public Number getCurrentPoolSize() { return threadPool.getPoolSize(); } public Number getCurrentTaskCount() { return threadPool.getTaskCount(); } public Number getCurrentQueueSize() { return threadPool.getQueue().size(); }
消息接收流
HystrixCommandStartStream、HystrixCommandCompletionStream、HystrixCollapserEventStream、HystrixThreadPoolCompletionStream、HystrixThreadPoolStartStream是hystrix的消息监听流,分别接收命令、合并命令、线程池发出的消息。
消息接收流使用了单例模式,每个key对应一个消息流。
public static HystrixCommandStartStream getInstance(HystrixCommandKey commandKey) { HystrixCommandStartStream initialStream = streams.get(commandKey.name()); if (initialStream != null) { return initialStream; } else { synchronized (HystrixCommandStartStream.class) { HystrixCommandStartStream existingStream = streams.get(commandKey.name()); if (existingStream == null) { HystrixCommandStartStream newStream = new HystrixCommandStartStream(commandKey); streams.putIfAbsent(commandKey.name(), newStream); return newStream; } else { return existingStream; } } } }
内部使用rxjava来实现消息机制
HystrixCommandStartStream(final HystrixCommandKey commandKey) { this.commandKey = commandKey; this.writeOnlySubject = new SerializedSubject<HystrixCommandExecutionStarted, HystrixCommandExecutionStarted>(PublishSubject.<HystrixCommandExecutionStarted>create()); this.readOnlyStream = writeOnlySubject.share(); }
HystrixThreadEventStream
hystrix事件接收流的统一处理类。
commandExecutionStarted方法向HystrixCommandStartStream发送HystrixCommandExecutionStarted消息,如果是线程执行的话向HystrixThreadPoolStartStream发送HystrixCommandExecutionStarted消息。executionDone方法向HystrixCommandCompletionStream发送HystrixCommandCompletion消息,如果线程执行的话向HystrixThreadPoolCompletionStream发送HystrixCommandCompletion消息;collapserResponseFromCache和collapserBatchExecuted方法分别向HystrixCollapserEventStream发送类型为RESPONSE_FROM_CACHE和BATCH_EXECUTED ADDED_TO_BATCH的HystrixCollapserEvent。
private final Subject<HystrixCommandExecutionStarted, HystrixCommandExecutionStarted> writeOnlyCommandStartSubject; private final Subject<HystrixCommandCompletion, HystrixCommandCompletion> writeOnlyCommandCompletionSubject; private final Subject<HystrixCollapserEvent, HystrixCollapserEvent> writeOnlyCollapserSubject; private static final ThreadLocal<HystrixThreadEventStream> threadLocalStreams = new ThreadLocal<HystrixThreadEventStream>() { @Override protected HystrixThreadEventStream initialValue() { return new HystrixThreadEventStream(Thread.currentThread()); } }; private static final Action1<HystrixCommandExecutionStarted> writeCommandStartsToShardedStreams = new Action1<HystrixCommandExecutionStarted>() { @Override public void call(HystrixCommandExecutionStarted event) { HystrixCommandStartStream commandStartStream = HystrixCommandStartStream.getInstance(event.getCommandKey()); commandStartStream.write(event); if (event.isExecutedInThread()) { HystrixThreadPoolStartStream threadPoolStartStream = HystrixThreadPoolStartStream.getInstance(event.getThreadPoolKey()); threadPoolStartStream.write(event); } } }; private static final Action1<HystrixCommandCompletion> writeCommandCompletionsToShardedStreams = new Action1<HystrixCommandCompletion>() { @Override public void call(HystrixCommandCompletion commandCompletion) { HystrixCommandCompletionStream commandStream = HystrixCommandCompletionStream.getInstance(commandCompletion.getCommandKey()); commandStream.write(commandCompletion); if (commandCompletion.isExecutedInThread() || commandCompletion.isResponseThreadPoolRejected()) { HystrixThreadPoolCompletionStream threadPoolStream = HystrixThreadPoolCompletionStream.getInstance(commandCompletion.getThreadPoolKey()); threadPoolStream.write(commandCompletion); } } }; private static final Action1<HystrixCollapserEvent> writeCollapserExecutionsToShardedStreams = new Action1<HystrixCollapserEvent>() { @Override public void call(HystrixCollapserEvent collapserEvent) { HystrixCollapserEventStream collapserStream = HystrixCollapserEventStream.getInstance(collapserEvent.getCollapserKey()); collapserStream.write(collapserEvent); } }; /* package */ HystrixThreadEventStream(Thread thread) { this.threadId = thread.getId(); this.threadName = thread.getName(); writeOnlyCommandStartSubject = PublishSubject.create(); writeOnlyCommandCompletionSubject = PublishSubject.create(); writeOnlyCollapserSubject = PublishSubject.create(); writeOnlyCommandStartSubject .onBackpressureBuffer() .doOnNext(writeCommandStartsToShardedStreams) .unsafeSubscribe(Subscribers.empty()); writeOnlyCommandCompletionSubject .onBackpressureBuffer() .doOnNext(writeCommandCompletionsToShardedStreams) .unsafeSubscribe(Subscribers.empty()); writeOnlyCollapserSubject .onBackpressureBuffer() .doOnNext(writeCollapserExecutionsToShardedStreams) .unsafeSubscribe(Subscribers.empty()); } public static HystrixThreadEventStream getInstance() { return threadLocalStreams.get(); } public void shutdown() { writeOnlyCommandStartSubject.onCompleted(); writeOnlyCommandCompletionSubject.onCompleted(); writeOnlyCollapserSubject.onCompleted(); } public void commandExecutionStarted(HystrixCommandKey commandKey, HystrixThreadPoolKey threadPoolKey,HystrixCommandProperties.ExecutionIsolationStrategy isolationStrategy, int currentConcurrency) { HystrixCommandExecutionStarted event = new HystrixCommandExecutionStarted(commandKey, threadPoolKey, isolationStrategy, currentConcurrency); writeOnlyCommandStartSubject.onNext(event); } public void executionDone(ExecutionResult executionResult, HystrixCommandKey commandKey, HystrixThreadPoolKey threadPoolKey) { HystrixCommandCompletion event = HystrixCommandCompletion.from(executionResult, commandKey, threadPoolKey); writeOnlyCommandCompletionSubject.onNext(event); } public void collapserResponseFromCache(HystrixCollapserKey collapserKey) { HystrixCollapserEvent collapserEvent = HystrixCollapserEvent.from(collapserKey, HystrixEventType.Collapser.RESPONSE_FROM_CACHE, 1); writeOnlyCollapserSubject.onNext(collapserEvent); } public void collapserBatchExecuted(HystrixCollapserKey collapserKey, int batchSize) { HystrixCollapserEvent batchExecution = HystrixCollapserEvent.from(collapserKey, HystrixEventType.Collapser.BATCH_EXECUTED, 1); HystrixCollapserEvent batchAdditions = HystrixCollapserEvent.from(collapserKey, HystrixEventType.Collapser.ADDED_TO_BATCH, batchSize); writeOnlyCollapserSubject.onNext(batchExecution); writeOnlyCollapserSubject.onNext(batchAdditions); }
消息体
HystrixCommandExecutionStarted
命令开始执行消息,内部包括了该命令的执行策略和并发数。
private final HystrixCommandProperties.ExecutionIsolationStrategy isolationStrategy; private final int currentConcurrency; public HystrixCommandExecutionStarted(HystrixCommandKey commandKey, HystrixThreadPoolKey threadPoolKey, HystrixCommandProperties.ExecutionIsolationStrategy isolationStrategy, int currentConcurrency) { super(commandKey, threadPoolKey); this.isolationStrategy = isolationStrategy; this.currentConcurrency = currentConcurrency; }
HystrixCommandCompletion
命令执行完成消息。内部包含执行结果对象ExecutionResult和请求上下文对象HystrixRequestContext。
protected final ExecutionResult executionResult; protected final HystrixRequestContext requestContext;
ExecutionResult
执行结果数据。
private final EventCounts eventCounts;//事件数量 private final Exception failedExecutionException;//失败异常 private final Exception executionException; //执行异常 private final long startTimestamp;//命令开始执行时间 private final int executionLatency; //执行run的时间 private final int userThreadLatency; //请求提交到执行结束的时间 private final boolean executionOccurred;//ture 执行过命令 false 未执行过命令 private final boolean isExecutedInThread;//ture 使用线程池执行 false 不是使用线程池执行 private final HystrixCollapserKey collapserKey;
EventCounts
记录各个事件的次数。
private final BitSet events; private final int numEmissions//emission次数 private final int numFallbackEmissions;//fallback次数 private final int numCollapsed;//合并格式
HystrixCollapserEvent
合并命令消息,内部包含合并命令key、事件类型、次数。
private final HystrixCollapserKey collapserKey; private final HystrixEventType.Collapser eventType; private final int count;
消息监听流
BucketedCounterStream
监听HystrixEvent消息,并对各个事件类型聚合一个时间段内的数据。
protected BucketedCounterStream(final HystrixEventStream<Event> inputEventStream, final int numBuckets, final int bucketSizeInMs, final Func2<Bucket, Event, Bucket> appendRawEventToBucket) { this.numBuckets = numBuckets; this.reduceBucketToSummary = new Func1<Observable<Event>, Observable<Bucket>>() { @Override public Observable<Bucket> call(Observable<Event> eventBucket) { return eventBucket.reduce(getEmptyBucketSummary(), appendRawEventToBucket); } }; final List<Bucket> emptyEventCountsToStart = new ArrayList<Bucket>(); for (int i = 0; i < numBuckets; i++) { emptyEventCountsToStart.add(getEmptyBucketSummary()); } this.bucketedStream = Observable.defer(new Func0<Observable<Bucket>>() { @Override public Observable<Bucket> call() { return inputEventStream .observe() .window(bucketSizeInMs, TimeUnit.MILLISECONDS) //bucket it by the counter window so we can emit to the next operator in time chunks, not on every OnNext .flatMap(reduceBucketToSummary) //for a given bucket, turn it into a long array containing counts of event types .startWith(emptyEventCountsToStart); //start it with empty arrays to make consumer logic as generic as possible (windows are always full) } }); }
BucketedCumulativeCounterStream
BucketedCounterStream子类,对聚合的数据进行持续统计。
protected BucketedCumulativeCounterStream(HystrixEventStream<Event> stream, int numBuckets, int bucketSizeInMs, Func2<Bucket, Event, Bucket> reduceCommandCompletion, Func2<Output, Bucket, Output> reduceBucket) { super(stream, numBuckets, bucketSizeInMs, reduceCommandCompletion); this.sourceStream = bucketedStream .scan(getEmptyOutputValue(), reduceBucket) .skip(numBuckets) .doOnSubscribe(new Action0() { @Override public void call() { isSourceCurrentlySubscribed.set(true); } }) .doOnUnsubscribe(new Action0() { @Override public void call() { isSourceCurrentlySubscribed.set(false); } }) .share() //multiple subscribers should get same data .onBackpressureDrop(); //if there are slow consumers, data should not buffer }
BucketedRollingCounterStream
BucketedCounterStream子类,对聚合的数据在窗口期内统计。
protected BucketedRollingCounterStream(HystrixEventStream<Event> stream, final int numBuckets, int bucketSizeInMs, final Func2<Bucket, Event, Bucket> appendRawEventToBucket, final Func2<Output, Bucket, Output> reduceBucket) { super(stream, numBuckets, bucketSizeInMs, appendRawEventToBucket); Func1<Observable<Bucket>, Observable<Output>> reduceWindowToSummary = new Func1<Observable<Bucket>, Observable<Output>>() { @Override public Observable<Output> call(Observable<Bucket> window) { return window.scan(getEmptyOutputValue(), reduceBucket).skip(numBuckets); } }; this.sourceStream = bucketedStream //stream broken up into buckets .window(numBuckets, 1) //emit overlapping windows of buckets .flatMap(reduceWindowToSummary) //convert a window of bucket-summaries into a single summary .doOnSubscribe(new Action0() { @Override public void call() { isSourceCurrentlySubscribed.set(true); } }) .doOnUnsubscribe(new Action0() { @Override public void call() { isSourceCurrentlySubscribed.set(false); } }) .share() //multiple subscribers should get same data .onBackpressureDrop(); //if there are slow consumers, data should not buffer }
CumulativeCollapserEventCounterStream、CumulativeCommandEventCounterStream、CumulativeThreadPoolEventCounterStream继承BucketedCumulativeCounterStream,分别监控合并命令,命令,线程池的各个事件,并持续合并各个事件的数据。
RollingCollapserEventCounterStream、RollingCommandEventCounterStream、RollingThreadPoolEventCounterStream继承BucketedRollingCounterStream分别监控合并命令,命令,线程池的各个事件,并合并窗口期内各个事件的数据。HealthCountsStream继承BucketedRollingCounterStream监控和计算调用的失败率。
RollingConcurrencyStream
监听HystrixCommandExecutionStarted消息,获得当前并发量,并统计窗口期内的最大并发量。
protected RollingConcurrencyStream(final HystrixEventStream<HystrixCommandExecutionStarted> inputEventStream, final int numBuckets, final int bucketSizeInMs) { final List<Integer> emptyRollingMaxBuckets = new ArrayList<Integer>(); for (int i = 0; i < numBuckets; i++) { emptyRollingMaxBuckets.add(0); } rollingMaxStream = inputEventStream .observe() .map(getConcurrencyCountFromEvent) .window(bucketSizeInMs, TimeUnit.MILLISECONDS) .flatMap(reduceStreamToMax) .startWith(emptyRollingMaxBuckets) .window(numBuckets, 1) .flatMap(reduceStreamToMax) .share() .onBackpressureDrop(); } private static final Func1<Observable<Integer>, Observable<Integer>> reduceStreamToMax = new Func1<Observable<Integer>, Observable<Integer>>() { @Override public Observable<Integer> call(Observable<Integer> observedConcurrency) { return observedConcurrency.reduce(0, reduceToMax); } };
RollingCommandMaxConcurrencyStream、RollingThreadPoolMaxConcurrencyStream分别监听HystrixCommandStartStream、HystrixThreadPoolStartStream消息流,统计窗口期内最大并发量。
RollingDistributionStream
统计某一数据的窗口期内分布情况。
protected RollingDistributionStream(final HystrixEventStream<Event> stream, final int numBuckets, final int bucketSizeInMs, final Func2<Histogram, Event, Histogram> addValuesToBucket) { final List<Histogram> emptyDistributionsToStart = new ArrayList<Histogram>(); for (int i = 0; i < numBuckets; i++) { emptyDistributionsToStart.add(CachedValuesHistogram.getNewHistogram()); } final Func1<Observable<Event>, Observable<Histogram>> reduceBucketToSingleDistribution = new Func1<Observable<Event>, Observable<Histogram>>() { @Override public Observable<Histogram> call(Observable<Event> bucket) { return bucket.reduce(CachedValuesHistogram.getNewHistogram(), addValuesToBucket); } }; rollingDistributionStream = stream .observe() .window(bucketSizeInMs, TimeUnit.MILLISECONDS) //stream of unaggregated buckets .flatMap(reduceBucketToSingleDistribution) //stream of aggregated Histograms .startWith(emptyDistributionsToStart) //stream of aggregated Histograms that starts with n empty .window(numBuckets, 1) //windowed stream: each OnNext is a stream of n Histograms .flatMap(reduceWindowToSingleDistribution) //reduced stream: each OnNext is a single Histogram .map(cacheHistogramValues) //convert to CachedValueHistogram (commonly-accessed values are cached) .share() .onBackpressureDrop(); }
RollingCollapserBatchSizeDistributionStream、RollingCommandLatencyDistributionStream、RollingCommandUserLatencyDistributionStream分别监听HystrixCollapserEventStream、HystrixCommandCompletionStream、HystrixCommandCompletionStream流来统计命令执行时间、执行总时间、ADDED_TO_BATCH的个数的百分比分布情况。
其他流
HystrixConfigurationStream
通过该数据流可以定时获取hystrix最新的properties配置信息,com.netflix.hystrix.contrib.sample.stream.HystrixConfigSseServlet就是用该流来获取配置信息。
public HystrixConfigurationStream(final int intervalInMilliseconds) { this.intervalInMilliseconds = intervalInMilliseconds; this.allConfigurationStream = Observable.interval(intervalInMilliseconds, TimeUnit.MILLISECONDS) .map(getAllConfig) .doOnSubscribe(new Action0() { @Override public void call() { isSourceCurrentlySubscribed.set(true); } }) .doOnUnsubscribe(new Action0() { @Override public void call() { isSourceCurrentlySubscribed.set(false); } }) .share() .onBackpressureDrop(); } private static final Func1<Long, HystrixConfiguration> getAllConfig = new Func1<Long, HystrixConfiguration>() { @Override public HystrixConfiguration call(Long timestamp) { return HystrixConfiguration.from( getAllCommandConfig.call(timestamp), getAllThreadPoolConfig.call(timestamp), getAllCollapserConfig.call(timestamp) ); } };
private static final Func1<Long, Map<HystrixCommandKey, HystrixCommandConfiguration>> getAllCommandConfig = new Func1<Long, Map<HystrixCommandKey, HystrixCommandConfiguration>>() { @Override public Map<HystrixCommandKey, HystrixCommandConfiguration> call(Long timestamp) { Map<HystrixCommandKey, HystrixCommandConfiguration> commandConfigPerKey = new HashMap<HystrixCommandKey, HystrixCommandConfiguration>(); for (HystrixCommandMetrics commandMetrics: HystrixCommandMetrics.getInstances()) { HystrixCommandKey commandKey = commandMetrics.getCommandKey(); HystrixThreadPoolKey threadPoolKey = commandMetrics.getThreadPoolKey(); HystrixCommandGroupKey groupKey = commandMetrics.getCommandGroup(); commandConfigPerKey.put(commandKey, sampleCommandConfiguration(commandKey, threadPoolKey, groupKey, commandMetrics.getProperties())); } return commandConfigPerKey; } }; private static final Func1<Long, Map<HystrixThreadPoolKey, HystrixThreadPoolConfiguration>> getAllThreadPoolConfig = new Func1<Long, Map<HystrixThreadPoolKey, HystrixThreadPoolConfiguration>>() { @Override public Map<HystrixThreadPoolKey, HystrixThreadPoolConfiguration> call(Long timestamp) { Map<HystrixThreadPoolKey, HystrixThreadPoolConfiguration> threadPoolConfigPerKey = new HashMap<HystrixThreadPoolKey, HystrixThreadPoolConfiguration>(); for (HystrixThreadPoolMetrics threadPoolMetrics: HystrixThreadPoolMetrics.getInstances()) { HystrixThreadPoolKey threadPoolKey = threadPoolMetrics.getThreadPoolKey(); threadPoolConfigPerKey.put(threadPoolKey, sampleThreadPoolConfiguration(threadPoolKey, threadPoolMetrics.getProperties())); } return threadPoolConfigPerKey; } }; private static final Func1<Long, Map<HystrixCollapserKey, HystrixCollapserConfiguration>> getAllCollapserConfig = new Func1<Long, Map<HystrixCollapserKey, HystrixCollapserConfiguration>>() { @Override public Map<HystrixCollapserKey, HystrixCollapserConfiguration> call(Long timestamp) { Map<HystrixCollapserKey, HystrixCollapserConfiguration> collapserConfigPerKey = new HashMap<HystrixCollapserKey, HystrixCollapserConfiguration>(); for (HystrixCollapserMetrics collapserMetrics: HystrixCollapserMetrics.getInstances()) { HystrixCollapserKey collapserKey = collapserMetrics.getCollapserKey(); collapserConfigPerKey.put(collapserKey, sampleCollapserConfiguration(collapserKey, collapserMetrics.getProperties())); } return collapserConfigPerKey; } };