View Javadoc

1   /**
2    * Copyright The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package org.apache.hadoop.hbase;
22  
23  import org.apache.hadoop.classification.InterfaceAudience;
24  import org.apache.hadoop.classification.InterfaceStability;
25  import org.apache.hadoop.hbase.protobuf.generated.ClusterStatusProtos;
26  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
27  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.Coprocessor;
28  import org.apache.hadoop.hbase.util.Bytes;
29  import org.apache.hadoop.hbase.util.Strings;
30  
31  import java.util.Arrays;
32  import java.util.List;
33  import java.util.Map;
34  import java.util.TreeMap;
35  import java.util.TreeSet;
36  
37  /**
38   * This class is used for exporting current state of load on a RegionServer.
39   */
40  @InterfaceAudience.Public
41  @InterfaceStability.Evolving
42  public class ServerLoad {
43    private int stores = 0;
44    private int storefiles = 0;
45    private int storeUncompressedSizeMB = 0;
46    private int storefileSizeMB = 0;
47    private int memstoreSizeMB = 0;
48    private int storefileIndexSizeMB = 0;
49    private int readRequestsCount = 0;
50    private int writeRequestsCount = 0;
51    private int rootIndexSizeKB = 0;
52    private int totalStaticIndexSizeKB = 0;
53    private int totalStaticBloomSizeKB = 0;
54    private long totalCompactingKVs = 0;
55    private long currentCompactedKVs = 0;
56    
57    public ServerLoad(ClusterStatusProtos.ServerLoad serverLoad) {
58      this.serverLoad = serverLoad;
59      for (ClusterStatusProtos.RegionLoad rl: serverLoad.getRegionLoadsList()) {
60        stores += rl.getStores();
61        storefiles += rl.getStorefiles();
62        storeUncompressedSizeMB += rl.getStoreUncompressedSizeMB();
63        storefileSizeMB += rl.getStorefileSizeMB();
64        memstoreSizeMB += rl.getMemstoreSizeMB();
65        storefileIndexSizeMB += rl.getStorefileIndexSizeMB();
66        readRequestsCount += rl.getReadRequestsCount();
67        writeRequestsCount += rl.getWriteRequestsCount();
68        rootIndexSizeKB += rl.getRootIndexSizeKB();
69        totalStaticIndexSizeKB += rl.getTotalStaticIndexSizeKB();
70        totalStaticBloomSizeKB += rl.getTotalStaticBloomSizeKB();
71        totalCompactingKVs += rl.getTotalCompactingKVs();
72        currentCompactedKVs += rl.getCurrentCompactedKVs();
73      }
74      
75    }
76  
77    // NOTE: Function name cannot start with "get" because then an OpenDataException is thrown because
78    // HBaseProtos.ServerLoad cannot be converted to an open data type(see HBASE-5967).
79    /* @return the underlying ServerLoad protobuf object */
80    public ClusterStatusProtos.ServerLoad obtainServerLoadPB() {
81      return serverLoad;
82    }
83  
84    protected ClusterStatusProtos.ServerLoad serverLoad;
85  
86    /* @return number of requests  since last report. */
87    public int getNumberOfRequests() {
88      return serverLoad.getNumberOfRequests();
89    }
90    public boolean hasNumberOfRequests() {
91      return serverLoad.hasNumberOfRequests();
92    }
93  
94    /* @return total Number of requests from the start of the region server. */
95    public int getTotalNumberOfRequests() {
96      return serverLoad.getTotalNumberOfRequests();
97    }
98    public boolean hasTotalNumberOfRequests() {
99      return serverLoad.hasTotalNumberOfRequests();
100   }
101 
102   /* @return the amount of used heap, in MB. */
103   public int getUsedHeapMB() {
104     return serverLoad.getUsedHeapMB();
105   }
106   public boolean hasUsedHeapMB() {
107     return serverLoad.hasUsedHeapMB();
108   }
109 
110   /* @return the maximum allowable size of the heap, in MB. */
111   public int getMaxHeapMB() {
112     return serverLoad.getMaxHeapMB();
113   }
114   public boolean hasMaxHeapMB() {
115     return serverLoad.hasMaxHeapMB();
116   }
117 
118   public int getStores() {
119     return stores;
120   }
121 
122   public int getStorefiles() {
123     return storefiles;
124   }
125 
126   public int getStoreUncompressedSizeMB() {
127     return storeUncompressedSizeMB;
128   }
129 
130   public int getStorefileSizeInMB() {
131     return storefileSizeMB;
132   }
133 
134   public int getMemstoreSizeInMB() {
135     return memstoreSizeMB;
136   }
137 
138   public int getStorefileIndexSizeInMB() {
139     return storefileIndexSizeMB;
140   }
141 
142   public int getReadRequestsCount() {
143     return readRequestsCount;
144   }
145 
146   public int getWriteRequestsCount() {
147     return writeRequestsCount;
148   }
149 
150   public int getRootIndexSizeKB() {
151     return rootIndexSizeKB;
152   }
153 
154   public int getTotalStaticIndexSizeKB() {
155     return totalStaticIndexSizeKB;
156   }
157 
158   public int getTotalStaticBloomSizeKB() {
159     return totalStaticBloomSizeKB;
160   }
161 
162   public long getTotalCompactingKVs() {
163     return totalCompactingKVs;
164   }
165 
166   public long getCurrentCompactedKVs() {
167     return currentCompactedKVs;
168   }
169 
170   /**
171    * @return the number of regions
172    */
173   public int getNumberOfRegions() {
174     return serverLoad.getRegionLoadsCount();
175   }
176 
177   public int getInfoServerPort() {
178     return serverLoad.getInfoServerPort();
179   }
180 
181   /**
182    * Originally, this method factored in the effect of requests going to the
183    * server as well. However, this does not interact very well with the current
184    * region rebalancing code, which only factors number of regions. For the
185    * interim, until we can figure out how to make rebalancing use all the info
186    * available, we're just going to make load purely the number of regions.
187    *
188    * @return load factor for this server
189    */
190   public int getLoad() {
191     // See above comment
192     // int load = numberOfRequests == 0 ? 1 : numberOfRequests;
193     // load *= numberOfRegions == 0 ? 1 : numberOfRegions;
194     // return load;
195     return getNumberOfRegions();
196   }
197 
198   /**
199    * @return region load metrics
200    */
201   public Map<byte[], RegionLoad> getRegionsLoad() {
202     Map<byte[], RegionLoad> regionLoads =
203       new TreeMap<byte[], RegionLoad>(Bytes.BYTES_COMPARATOR);
204     for (ClusterStatusProtos.RegionLoad rl : serverLoad.getRegionLoadsList()) {
205       RegionLoad regionLoad = new RegionLoad(rl);
206       regionLoads.put(regionLoad.getName(), regionLoad);
207     }
208     return regionLoads;
209   }
210 
211   /**
212    * Return the RegionServer-level coprocessors
213    * @return string array of loaded RegionServer-level coprocessors
214    */
215   public String[] getRegionServerCoprocessors() {
216     List<Coprocessor> list = obtainServerLoadPB().getCoprocessorsList();
217     String [] ret = new String[list.size()];
218     int i = 0;
219     for (Coprocessor elem : list) {
220       ret[i++] = elem.getName();
221     }
222 
223     return ret;
224   }
225 
226   /**
227    * Return the RegionServer-level and Region-level coprocessors
228    * @return string array of loaded RegionServer-level and
229    *         Region-level coprocessors
230    */
231   public String[] getRsCoprocessors() {
232     // Need a set to remove duplicates, but since generated Coprocessor class
233     // is not Comparable, make it a Set<String> instead of Set<Coprocessor>
234     TreeSet<String> coprocessSet = new TreeSet<String>();
235     for (Coprocessor coprocessor : obtainServerLoadPB().getCoprocessorsList()) {
236       coprocessSet.add(coprocessor.getName());
237     }
238     return coprocessSet.toArray(new String[0]);
239   }
240 
241   /**
242    * @return number of requests per second received since the last report
243    */
244   public double getRequestsPerSecond() {
245     return getNumberOfRequests();
246   }
247 
248   /**
249    * @see java.lang.Object#toString()
250    */
251   @Override
252   public String toString() {
253      StringBuilder sb =
254         Strings.appendKeyValue(new StringBuilder(), "requestsPerSecond",
255           Double.valueOf(getRequestsPerSecond()));
256     Strings.appendKeyValue(sb, "numberOfOnlineRegions", Integer.valueOf(getNumberOfRegions()));
257     sb = Strings.appendKeyValue(sb, "usedHeapMB", Integer.valueOf(this.getUsedHeapMB()));
258     sb = Strings.appendKeyValue(sb, "maxHeapMB", Integer.valueOf(getMaxHeapMB()));
259     sb = Strings.appendKeyValue(sb, "numberOfStores", Integer.valueOf(this.stores));
260     sb = Strings.appendKeyValue(sb, "numberOfStorefiles", Integer.valueOf(this.storefiles));
261     sb =
262         Strings.appendKeyValue(sb, "storefileUncompressedSizeMB",
263           Integer.valueOf(this.storeUncompressedSizeMB));
264     sb = Strings.appendKeyValue(sb, "storefileSizeMB", Integer.valueOf(this.storefileSizeMB));
265     if (this.storeUncompressedSizeMB != 0) {
266       sb =
267           Strings.appendKeyValue(
268             sb,
269             "compressionRatio",
270             String.format("%.4f", (float) this.storefileSizeMB
271                 / (float) this.storeUncompressedSizeMB));
272     }
273     sb = Strings.appendKeyValue(sb, "memstoreSizeMB", Integer.valueOf(this.memstoreSizeMB));
274     sb =
275         Strings.appendKeyValue(sb, "storefileIndexSizeMB",
276           Integer.valueOf(this.storefileIndexSizeMB));
277     sb = Strings.appendKeyValue(sb, "readRequestsCount", Long.valueOf(this.readRequestsCount));
278     sb = Strings.appendKeyValue(sb, "writeRequestsCount", Long.valueOf(this.writeRequestsCount));
279     sb = Strings.appendKeyValue(sb, "rootIndexSizeKB", Integer.valueOf(this.rootIndexSizeKB));
280     sb =
281         Strings.appendKeyValue(sb, "totalStaticIndexSizeKB",
282           Integer.valueOf(this.totalStaticIndexSizeKB));
283     sb =
284         Strings.appendKeyValue(sb, "totalStaticBloomSizeKB",
285           Integer.valueOf(this.totalStaticBloomSizeKB));
286     sb = Strings.appendKeyValue(sb, "totalCompactingKVs", Long.valueOf(this.totalCompactingKVs));
287     sb = Strings.appendKeyValue(sb, "currentCompactedKVs", Long.valueOf(this.currentCompactedKVs));
288     float compactionProgressPct = Float.NaN;
289     if (this.totalCompactingKVs > 0) {
290       compactionProgressPct =
291           Float.valueOf((float) this.currentCompactedKVs / this.totalCompactingKVs);
292     }
293     sb = Strings.appendKeyValue(sb, "compactionProgressPct", compactionProgressPct);
294 
295     String[] coprocessorStrings = getRsCoprocessors();
296     if (coprocessorStrings != null) {
297       sb = Strings.appendKeyValue(sb, "coprocessors", Arrays.toString(coprocessorStrings));
298     }
299     return sb.toString();
300   }
301 
302   public static final ServerLoad EMPTY_SERVERLOAD =
303     new ServerLoad(ClusterStatusProtos.ServerLoad.newBuilder().build());
304 }