-
Notifications
You must be signed in to change notification settings - Fork 3.4k
HBASE-27466: Making metrics instance containing one or more connections. #4874
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 11 commits
9a525b7
7bbfc81
c39aec2
9a7d4fa
ed9b1e3
b51866c
3eb93dc
9bbfe2e
3abc7ab
e12e75e
77652cc
298ece2
b9234b3
80f135a
c28a248
be2d559
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,10 @@ | |
| import com.codahale.metrics.MetricRegistry; | ||
| import com.codahale.metrics.RatioGauge; | ||
| import com.codahale.metrics.Timer; | ||
| import java.util.ArrayList; | ||
| import java.util.HashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
| import java.util.concurrent.ConcurrentMap; | ||
| import java.util.concurrent.ConcurrentSkipListMap; | ||
|
|
@@ -47,13 +51,46 @@ | |
| /** | ||
| * This class is for maintaining the various connection statistics and publishing them through the | ||
| * metrics interfaces. This class manages its own {@link MetricRegistry} and {@link JmxReporter} so | ||
| * as to not conflict with other uses of Yammer Metrics within the client application. Instantiating | ||
| * this class implicitly creates and "starts" instances of these classes; be sure to call | ||
| * {@link #shutdown()} to terminate the thread pools they allocate. | ||
| * as to not conflict with other uses of Yammer Metrics within the client application. Calling | ||
| * {@link #getMetricsConnection()} implicitly creates and "starts" instances of these classes; be | ||
| * sure to call {@link #deleteMetricsConnection()} to terminate the thread pools they allocate. The | ||
| * metrics reporter will be shutdown {@link #shutdown()} when all connections within this metrics | ||
| * instances are closed. | ||
| */ | ||
| @InterfaceAudience.Private | ||
| public class MetricsConnection implements StatisticTrackable { | ||
|
|
||
| static final Map<String, MetricsConnection> METRICS_INSTANCES = | ||
| new HashMap<String, MetricsConnection>(); | ||
|
|
||
| static MetricsConnection getMetricsConnection(final String scope, | ||
vli02 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Supplier<ThreadPoolExecutor> batchPool, Supplier<ThreadPoolExecutor> metaPool) { | ||
| MetricsConnection metrics; | ||
| synchronized (METRICS_INSTANCES) { | ||
|
||
| metrics = METRICS_INSTANCES.get(scope); | ||
| if (metrics == null) { | ||
| metrics = new MetricsConnection(scope, batchPool, metaPool); | ||
| METRICS_INSTANCES.put(scope, metrics); | ||
| } else { | ||
| metrics.addThreadPools(batchPool, metaPool); | ||
| } | ||
| metrics.incrConnectionCount(); | ||
| } | ||
| return metrics; | ||
| } | ||
|
|
||
| static void deleteMetricsConnection(final String scope) { | ||
| synchronized (METRICS_INSTANCES) { | ||
vli02 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| MetricsConnection metrics = METRICS_INSTANCES.get(scope); | ||
| if (metrics == null) return; | ||
| metrics.decrConnectionCount(); | ||
vli02 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if (metrics.getConnectionCount() == 0) { | ||
| METRICS_INSTANCES.remove(scope); | ||
| metrics.shutdown(); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** Set this key to {@code true} to enable metrics collection of client requests. */ | ||
| public static final String CLIENT_SIDE_METRICS_ENABLED_KEY = "hbase.client.metrics.enable"; | ||
|
|
||
|
|
@@ -295,8 +332,13 @@ public Counter newMetric(Class<?> clazz, String name, String scope) { | |
| } | ||
| }; | ||
|
|
||
| // List of thread pool per connection of the metrics. | ||
| private List<Supplier<ThreadPoolExecutor>> batchPools = new ArrayList<>(); | ||
| private List<Supplier<ThreadPoolExecutor>> metaPools = new ArrayList<>(); | ||
vli02 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| // static metrics | ||
|
|
||
| protected final Counter connectionCount; | ||
| protected final Counter metaCacheHits; | ||
| protected final Counter metaCacheMisses; | ||
| protected final CallTracker getTracker; | ||
|
|
@@ -331,30 +373,52 @@ public Counter newMetric(Class<?> clazz, String name, String scope) { | |
| protected final ConcurrentMap<String, Counter> rpcCounters = | ||
| new ConcurrentHashMap<>(CAPACITY, LOAD_FACTOR, CONCURRENCY_LEVEL); | ||
|
|
||
| MetricsConnection(String scope, Supplier<ThreadPoolExecutor> batchPool, | ||
| private MetricsConnection(String scope, Supplier<ThreadPoolExecutor> batchPool, | ||
| Supplier<ThreadPoolExecutor> metaPool) { | ||
| this.scope = scope; | ||
| addThreadPools(batchPool, metaPool); | ||
| this.registry = new MetricRegistry(); | ||
| this.registry.register(getExecutorPoolName(), new RatioGauge() { | ||
| @Override | ||
| protected Ratio getRatio() { | ||
| ThreadPoolExecutor pool = batchPool.get(); | ||
| if (pool == null) { | ||
| return Ratio.of(0, 0); | ||
| int numerator = 0; | ||
vli02 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| int denominator = 0; | ||
| for (Supplier<ThreadPoolExecutor> poolSupplier : batchPools) { | ||
| ThreadPoolExecutor pool = poolSupplier.get(); | ||
| if (pool != null) { | ||
| int activeCount = pool.getActiveCount(); | ||
| int maxPoolSize = pool.getMaximumPoolSize(); | ||
| /* The max thread usage ratio among batch pools of all connections */ | ||
| if (numerator == 0 || (numerator * maxPoolSize) < (activeCount * denominator)) { | ||
| numerator = activeCount; | ||
| denominator = maxPoolSize; | ||
| } | ||
vli02 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
| return Ratio.of(pool.getActiveCount(), pool.getMaximumPoolSize()); | ||
| return Ratio.of(numerator, denominator); | ||
| } | ||
| }); | ||
| this.registry.register(getMetaPoolName(), new RatioGauge() { | ||
| @Override | ||
| protected Ratio getRatio() { | ||
| ThreadPoolExecutor pool = metaPool.get(); | ||
| if (pool == null) { | ||
| return Ratio.of(0, 0); | ||
| int numerator = 0; | ||
| int denominator = 0; | ||
| for (Supplier<ThreadPoolExecutor> poolSupplier : metaPools) { | ||
| ThreadPoolExecutor pool = poolSupplier.get(); | ||
| if (pool != null) { | ||
| int activeCount = pool.getActiveCount(); | ||
| int maxPoolSize = pool.getMaximumPoolSize(); | ||
| /* The max thread usage ratio among meta lookup pools of all connections */ | ||
| if (numerator == 0 || (numerator * maxPoolSize) < (activeCount * denominator)) { | ||
| numerator = activeCount; | ||
| denominator = maxPoolSize; | ||
| } | ||
| } | ||
| } | ||
| return Ratio.of(pool.getActiveCount(), pool.getMaximumPoolSize()); | ||
| return Ratio.of(numerator, denominator); | ||
| } | ||
| }); | ||
| this.connectionCount = registry.counter(name(this.getClass(), "connectionCount", scope)); | ||
| this.metaCacheHits = registry.counter(name(this.getClass(), "metaCacheHits", scope)); | ||
| this.metaCacheMisses = registry.counter(name(this.getClass(), "metaCacheMisses", scope)); | ||
| this.metaCacheNumClearServer = | ||
|
|
@@ -396,10 +460,6 @@ MetricRegistry getMetricRegistry() { | |
| return registry; | ||
| } | ||
|
|
||
| public void shutdown() { | ||
| this.reporter.stop(); | ||
| } | ||
|
|
||
| /** Produce an instance of {@link CallStats} for clients to attach to RPCs. */ | ||
| public static CallStats newCallStats() { | ||
| // TODO: instance pool to reduce GC? | ||
|
|
@@ -457,6 +517,27 @@ public void incrementServerOverloadedBackoffTime(long time, TimeUnit timeUnit) { | |
| overloadedBackoffTimer.update(time, timeUnit); | ||
| } | ||
|
|
||
| /** Return the connection count of the metrics within a scope */ | ||
| public long getConnectionCount() { | ||
| return connectionCount.getCount(); | ||
vli02 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| /** Increment the connection count of the metrics within a scope */ | ||
| private void incrConnectionCount() { | ||
| connectionCount.inc(); | ||
| } | ||
|
|
||
| /** Decrement the connection count of the metrics within a scope */ | ||
| private void decrConnectionCount() { | ||
| connectionCount.dec(); | ||
| } | ||
|
|
||
| /** Add thread pools of additional connections to the metrics */ | ||
| private void addThreadPools(Supplier batchPool, Supplier metaPool) { | ||
vli02 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| batchPools.add(batchPool); | ||
| metaPools.add(metaPool); | ||
| } | ||
|
|
||
| /** | ||
| * Get a metric for {@code key} from {@code map}, or create it with {@code factory}. | ||
| */ | ||
|
|
@@ -474,6 +555,10 @@ private void updateRpcGeneric(String methodName, CallStats stats) { | |
| .update(stats.getResponseSizeBytes()); | ||
| } | ||
|
|
||
| private void shutdown() { | ||
| this.reporter.stop(); | ||
| } | ||
|
|
||
| /** Report RPC context to metrics system. */ | ||
| public void updateRpc(MethodDescriptor method, Message param, CallStats stats) { | ||
| int callsPerServer = stats.getConcurrentCallsPerServer(); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.