View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.regionserver;
19  
20  import java.util.Collection;
21  import java.util.concurrent.ScheduledExecutorService;
22  import java.util.concurrent.TimeUnit;
23  
24  import org.apache.commons.lang.StringUtils;
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.hadoop.classification.InterfaceAudience;
28  import org.apache.hadoop.hbase.CompatibilitySingletonFactory;
29  import org.apache.hadoop.hbase.HConstants;
30  import org.apache.hadoop.hbase.HDFSBlocksDistribution;
31  import org.apache.hadoop.hbase.ServerName;
32  import org.apache.hadoop.hbase.io.hfile.BlockCache;
33  import org.apache.hadoop.hbase.io.hfile.CacheConfig;
34  import org.apache.hadoop.hbase.io.hfile.CacheStats;
35  import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
36  import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
37  import org.apache.hadoop.metrics2.MetricsExecutor;
38  
39  /**
40   * Impl for exposing HRegionServer Information through Hadoop's metrics 2 system.
41   */
42  @InterfaceAudience.Private
43  class MetricsRegionServerWrapperImpl
44      implements MetricsRegionServerWrapper {
45  
46    public static final Log LOG = LogFactory.getLog(MetricsRegionServerWrapperImpl.class);
47  
48    private final HRegionServer regionServer;
49  
50    private BlockCache blockCache;
51  
52    private volatile long numStores = 0;
53    private volatile long numHLogFiles = 0;
54    private volatile long hlogFileSize = 0;
55    private volatile long numStoreFiles = 0;
56    private volatile long memstoreSize = 0;
57    private volatile long storeFileSize = 0;
58    private volatile double requestsPerSecond = 0.0;
59    private volatile long readRequestsCount = 0;
60    private volatile long writeRequestsCount = 0;
61    private volatile long checkAndMutateChecksFailed = 0;
62    private volatile long checkAndMutateChecksPassed = 0;
63    private volatile long storefileIndexSize = 0;
64    private volatile long totalStaticIndexSize = 0;
65    private volatile long totalStaticBloomSize = 0;
66    private volatile long numMutationsWithoutWAL = 0;
67    private volatile long dataInMemoryWithoutWAL = 0;
68    private volatile int percentFileLocal = 0;
69  
70    private CacheStats cacheStats;
71    private ScheduledExecutorService executor;
72    private Runnable runnable;
73    private long period;
74  
75    public MetricsRegionServerWrapperImpl(final HRegionServer regionServer) {
76      this.regionServer = regionServer;
77      initBlockCache();
78  
79      this.period =
80          regionServer.conf.getLong(HConstants.REGIONSERVER_METRICS_PERIOD,
81            HConstants.DEFAULT_REGIONSERVER_METRICS_PERIOD);
82  
83      this.executor = CompatibilitySingletonFactory.getInstance(MetricsExecutor.class).getExecutor();
84      this.runnable = new RegionServerMetricsWrapperRunnable();
85      this.executor.scheduleWithFixedDelay(this.runnable, this.period, this.period,
86        TimeUnit.MILLISECONDS);
87  
88      if (LOG.isInfoEnabled()) {
89        LOG.info("Computing regionserver metrics every " + this.period + " milliseconds");
90      }
91    }
92  
93    /**
94     * It's possible that due to threading the block cache could not be initialized
95     * yet (testing multiple region servers in one jvm).  So we need to try and initialize
96     * the blockCache and cacheStats reference multiple times until we succeed.
97     */
98    private synchronized  void initBlockCache() {
99      CacheConfig cacheConfig = this.regionServer.cacheConfig;
100     if (cacheConfig != null && this.blockCache == null) {
101       this.blockCache = cacheConfig.getBlockCache();
102     }
103 
104     if (this.blockCache != null && this.cacheStats == null) {
105       this.cacheStats = blockCache.getStats();
106     }
107   }
108 
109   @Override
110   public String getClusterId() {
111     return regionServer.getClusterId();
112   }
113 
114   @Override
115   public long getStartCode() {
116     return regionServer.getStartcode();
117   }
118 
119   @Override
120   public String getZookeeperQuorum() {
121     ZooKeeperWatcher zk = regionServer.getZooKeeper();
122     if (zk == null) {
123       return "";
124     }
125     return zk.getQuorum();
126   }
127 
128   @Override
129   public String getCoprocessors() {
130     String[] coprocessors = regionServer.getRegionServerCoprocessors();
131     if (coprocessors == null || coprocessors.length == 0) {
132       return "";
133     }
134     return StringUtils.join(coprocessors, ", ");
135   }
136 
137   @Override
138   public String getServerName() {
139     ServerName serverName = regionServer.getServerName();
140     if (serverName == null) {
141       return "";
142     }
143     return serverName.getServerName();
144   }
145 
146   @Override
147   public long getNumOnlineRegions() {
148     Collection<HRegion> onlineRegionsLocalContext = regionServer.getOnlineRegionsLocalContext();
149     if (onlineRegionsLocalContext == null) {
150       return 0;
151     }
152     return onlineRegionsLocalContext.size();
153   }
154 
155   @Override
156   public long getTotalRequestCount() {
157     return regionServer.rpcServices.requestCount.get();
158   }
159 
160   @Override
161   public int getCompactionQueueSize() {
162     //The thread could be zero.  if so assume there is no queue.
163     if (this.regionServer.compactSplitThread == null) {
164       return 0;
165     }
166     return this.regionServer.compactSplitThread.getCompactionQueueSize();
167   }
168 
169   @Override
170   public int getSmallCompactionQueueSize() {
171     //The thread could be zero.  if so assume there is no queue.
172     if (this.regionServer.compactSplitThread == null) {
173       return 0;
174     }
175     return this.regionServer.compactSplitThread.getSmallCompactionQueueSize();
176   }
177 
178   @Override
179   public int getLargeCompactionQueueSize() {
180     //The thread could be zero.  if so assume there is no queue.
181     if (this.regionServer.compactSplitThread == null) {
182       return 0;
183     }
184     return this.regionServer.compactSplitThread.getLargeCompactionQueueSize();
185   }
186 
187   @Override
188   public int getFlushQueueSize() {
189     //If there is no flusher there should be no queue.
190     if (this.regionServer.cacheFlusher == null) {
191       return 0;
192     }
193     return this.regionServer.cacheFlusher.getFlushQueueSize();
194   }
195 
196   @Override
197   public long getBlockCacheCount() {
198     if (this.blockCache == null) {
199       return 0;
200     }
201     return this.blockCache.getBlockCount();
202   }
203 
204   @Override
205   public long getBlockCacheSize() {
206     if (this.blockCache == null) {
207       return 0;
208     }
209     return this.blockCache.getCurrentSize();
210   }
211 
212   @Override
213   public long getBlockCacheFreeSize() {
214     if (this.blockCache == null) {
215       return 0;
216     }
217     return this.blockCache.getFreeSize();
218   }
219 
220   @Override
221   public long getBlockCacheHitCount() {
222     if (this.cacheStats == null) {
223       return 0;
224     }
225     return this.cacheStats.getHitCount();
226   }
227 
228   @Override
229   public long getBlockCacheMissCount() {
230     if (this.cacheStats == null) {
231       return 0;
232     }
233     return this.cacheStats.getMissCount();
234   }
235 
236   @Override
237   public long getBlockCacheEvictedCount() {
238     if (this.cacheStats == null) {
239       return 0;
240     }
241     return this.cacheStats.getEvictedCount();
242   }
243 
244   @Override
245   public double getBlockCacheHitPercent() {
246     if (this.cacheStats == null) {
247       return 0;
248     }
249     return (int) (this.cacheStats.getHitRatio() * 100);
250   }
251 
252   @Override
253   public int getBlockCacheHitCachingPercent() {
254     if (this.cacheStats == null) {
255       return 0;
256     }
257     return (int) (this.cacheStats.getHitCachingRatio() * 100);
258   }
259 
260   @Override public void forceRecompute() {
261     this.runnable.run();
262   }
263 
264   @Override
265   public long getNumStores() {
266     return numStores;
267   }
268   
269   @Override
270   public long getNumHLogFiles() {
271     return numHLogFiles;
272   }
273 
274   @Override
275   public long getHLogFileSize() {
276     return hlogFileSize;
277   }
278   
279   @Override
280   public long getNumStoreFiles() {
281     return numStoreFiles;
282   }
283 
284   @Override
285   public long getMemstoreSize() {
286     return memstoreSize;
287   }
288 
289   @Override
290   public long getStoreFileSize() {
291     return storeFileSize;
292   }
293 
294   @Override public double getRequestsPerSecond() {
295     return requestsPerSecond;
296   }
297 
298   @Override
299   public long getReadRequestsCount() {
300     return readRequestsCount;
301   }
302 
303   @Override
304   public long getWriteRequestsCount() {
305     return writeRequestsCount;
306   }
307 
308   @Override
309   public long getCheckAndMutateChecksFailed() {
310     return checkAndMutateChecksFailed;
311   }
312 
313   @Override
314   public long getCheckAndMutateChecksPassed() {
315     return checkAndMutateChecksPassed;
316   }
317 
318   @Override
319   public long getStoreFileIndexSize() {
320     return storefileIndexSize;
321   }
322 
323   @Override
324   public long getTotalStaticIndexSize() {
325     return totalStaticIndexSize;
326   }
327 
328   @Override
329   public long getTotalStaticBloomSize() {
330     return totalStaticBloomSize;
331   }
332 
333   @Override
334   public long getNumMutationsWithoutWAL() {
335     return numMutationsWithoutWAL;
336   }
337 
338   @Override
339   public long getDataInMemoryWithoutWAL() {
340     return dataInMemoryWithoutWAL;
341   }
342 
343   @Override
344   public int getPercentFileLocal() {
345     return percentFileLocal;
346   }
347 
348   @Override
349   public long getUpdatesBlockedTime() {
350     if (this.regionServer.cacheFlusher == null) {
351       return 0;
352     }
353     return this.regionServer.cacheFlusher.getUpdatesBlockedMsHighWater().get();
354   }
355 
356 
357   /**
358    * This is the runnable that will be executed on the executor every PERIOD number of seconds
359    * It will take metrics/numbers from all of the regions and use them to compute point in
360    * time metrics.
361    */
362   public class RegionServerMetricsWrapperRunnable implements Runnable {
363 
364     private long lastRan = 0;
365     private long lastRequestCount = 0;
366 
367     @Override
368     synchronized public void run() {
369       initBlockCache();
370       cacheStats = blockCache.getStats();
371 
372       HDFSBlocksDistribution hdfsBlocksDistribution =
373           new HDFSBlocksDistribution();
374 
375       long tempNumStores = 0;
376       long tempNumStoreFiles = 0;
377       long tempMemstoreSize = 0;
378       long tempStoreFileSize = 0;
379       long tempReadRequestsCount = 0;
380       long tempWriteRequestsCount = 0;
381       long tempCheckAndMutateChecksFailed = 0;
382       long tempCheckAndMutateChecksPassed = 0;
383       long tempStorefileIndexSize = 0;
384       long tempTotalStaticIndexSize = 0;
385       long tempTotalStaticBloomSize = 0;
386       long tempNumMutationsWithoutWAL = 0;
387       long tempDataInMemoryWithoutWAL = 0;
388       int tempPercentFileLocal = 0;
389 
390 
391       for (HRegion r : regionServer.getOnlineRegionsLocalContext()) {
392         tempNumMutationsWithoutWAL += r.numMutationsWithoutWAL.get();
393         tempDataInMemoryWithoutWAL += r.dataInMemoryWithoutWAL.get();
394         tempReadRequestsCount += r.readRequestsCount.get();
395         tempWriteRequestsCount += r.writeRequestsCount.get();
396         tempCheckAndMutateChecksFailed += r.checkAndMutateChecksFailed.get();
397         tempCheckAndMutateChecksPassed += r.checkAndMutateChecksPassed.get();
398         tempNumStores += r.stores.size();
399         for (Store store : r.stores.values()) {
400           tempNumStoreFiles += store.getStorefilesCount();
401           tempMemstoreSize += store.getMemStoreSize();
402           tempStoreFileSize += store.getStorefilesSize();
403           tempStorefileIndexSize += store.getStorefilesIndexSize();
404           tempTotalStaticBloomSize += store.getTotalStaticBloomSize();
405           tempTotalStaticIndexSize += store.getTotalStaticIndexSize();
406         }
407 
408         hdfsBlocksDistribution.add(r.getHDFSBlocksDistribution());
409       }
410 
411       float localityIndex = hdfsBlocksDistribution.getBlockLocalityIndex(
412           regionServer.getServerName().getHostname());
413       tempPercentFileLocal = (int) (localityIndex * 100);
414 
415 
416       //Compute the number of requests per second
417       long currentTime = EnvironmentEdgeManager.currentTimeMillis();
418 
419       // assume that it took PERIOD seconds to start the executor.
420       // this is a guess but it's a pretty good one.
421       if (lastRan == 0) {
422         lastRan = currentTime - (period * 1000);
423       }
424 
425 
426       //If we've time traveled keep the last requests per second.
427       if ((currentTime - lastRan) > 0) {
428         long currentRequestCount = getTotalRequestCount();
429         requestsPerSecond = (currentRequestCount - lastRequestCount) / ((currentTime - lastRan) / 1000.0);
430         lastRequestCount = currentRequestCount;
431       }
432       lastRan = currentTime;
433 
434       //Copy over computed values so that no thread sees half computed values.
435       numStores = tempNumStores;
436       long tempNumHLogFiles = regionServer.hlog.getNumLogFiles();
437       // meta logs
438       if (regionServer.hlogForMeta != null) {
439         tempNumHLogFiles += regionServer.hlogForMeta.getNumLogFiles();
440       }
441       numHLogFiles = tempNumHLogFiles;
442       
443       long tempHlogFileSize = regionServer.hlog.getLogFileSize();
444       if (regionServer.hlogForMeta != null) {
445         tempHlogFileSize += regionServer.hlogForMeta.getLogFileSize();
446       }
447       hlogFileSize = tempHlogFileSize;
448       
449       numStoreFiles = tempNumStoreFiles;
450       memstoreSize = tempMemstoreSize;
451       storeFileSize = tempStoreFileSize;
452       readRequestsCount = tempReadRequestsCount;
453       writeRequestsCount = tempWriteRequestsCount;
454       checkAndMutateChecksFailed = tempCheckAndMutateChecksFailed;
455       checkAndMutateChecksPassed = tempCheckAndMutateChecksPassed;
456       storefileIndexSize = tempStorefileIndexSize;
457       totalStaticIndexSize = tempTotalStaticIndexSize;
458       totalStaticBloomSize = tempTotalStaticBloomSize;
459       numMutationsWithoutWAL = tempNumMutationsWithoutWAL;
460       dataInMemoryWithoutWAL = tempDataInMemoryWithoutWAL;
461       percentFileLocal = tempPercentFileLocal;
462     }
463   }
464 }