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