HBASE-25026 Create a metric to track full region scans RPCs
Add new metric rpcFullScanRequestCount to track number of requests that are full region scans. Can be used to notify user to check if this is truly intended. Signed-off-by Anoop Sam John <anoopsamjohn@apache.org> Signed-off-by Ramkrishna S Vasudevan <ramkrishna@apache.org>
This commit is contained in:
parent
c07f27e025
commit
300b0a650f
|
@ -571,6 +571,9 @@ public interface MetricsRegionServerSource extends BaseSource, JvmPauseMonitorSo
|
||||||
String RPC_SCAN_REQUEST_COUNT = "rpcScanRequestCount";
|
String RPC_SCAN_REQUEST_COUNT = "rpcScanRequestCount";
|
||||||
String RPC_SCAN_REQUEST_COUNT_DESC =
|
String RPC_SCAN_REQUEST_COUNT_DESC =
|
||||||
"Number of rpc scan requests this RegionServer has answered.";
|
"Number of rpc scan requests this RegionServer has answered.";
|
||||||
|
String RPC_FULL_SCAN_REQUEST_COUNT = "rpcFullScanRequestCount";
|
||||||
|
String RPC_FULL_SCAN_REQUEST_COUNT_DESC =
|
||||||
|
"Number of rpc scan requests that were possible full region scans.";
|
||||||
String RPC_MULTI_REQUEST_COUNT = "rpcMultiRequestCount";
|
String RPC_MULTI_REQUEST_COUNT = "rpcMultiRequestCount";
|
||||||
String RPC_MULTI_REQUEST_COUNT_DESC =
|
String RPC_MULTI_REQUEST_COUNT_DESC =
|
||||||
"Number of rpc multi requests this RegionServer has answered.";
|
"Number of rpc multi requests this RegionServer has answered.";
|
||||||
|
|
|
@ -351,6 +351,8 @@ public class MetricsRegionServerSourceImpl
|
||||||
rsWrap.getWriteRequestsCount())
|
rsWrap.getWriteRequestsCount())
|
||||||
.addCounter(Interns.info(RPC_GET_REQUEST_COUNT, RPC_GET_REQUEST_COUNT_DESC),
|
.addCounter(Interns.info(RPC_GET_REQUEST_COUNT, RPC_GET_REQUEST_COUNT_DESC),
|
||||||
rsWrap.getRpcGetRequestsCount())
|
rsWrap.getRpcGetRequestsCount())
|
||||||
|
.addCounter(Interns.info(RPC_FULL_SCAN_REQUEST_COUNT, RPC_FULL_SCAN_REQUEST_COUNT_DESC),
|
||||||
|
rsWrap.getRpcFullScanRequestsCount())
|
||||||
.addCounter(Interns.info(RPC_SCAN_REQUEST_COUNT, RPC_SCAN_REQUEST_COUNT_DESC),
|
.addCounter(Interns.info(RPC_SCAN_REQUEST_COUNT, RPC_SCAN_REQUEST_COUNT_DESC),
|
||||||
rsWrap.getRpcScanRequestsCount())
|
rsWrap.getRpcScanRequestsCount())
|
||||||
.addCounter(Interns.info(RPC_MULTI_REQUEST_COUNT, RPC_MULTI_REQUEST_COUNT_DESC),
|
.addCounter(Interns.info(RPC_MULTI_REQUEST_COUNT, RPC_MULTI_REQUEST_COUNT_DESC),
|
||||||
|
|
|
@ -492,6 +492,11 @@ public interface MetricsRegionServerWrapper {
|
||||||
*/
|
*/
|
||||||
long getRpcScanRequestsCount();
|
long getRpcScanRequestsCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of full region rpc scan requests to this region server.
|
||||||
|
*/
|
||||||
|
long getRpcFullScanRequestsCount();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of rpc multi requests to this region server.
|
* Get the number of rpc multi requests to this region server.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2806,6 +2806,7 @@ public class HRegionServer extends Thread implements
|
||||||
rpcServices.requestCount.reset();
|
rpcServices.requestCount.reset();
|
||||||
rpcServices.rpcGetRequestCount.reset();
|
rpcServices.rpcGetRequestCount.reset();
|
||||||
rpcServices.rpcScanRequestCount.reset();
|
rpcServices.rpcScanRequestCount.reset();
|
||||||
|
rpcServices.rpcFullScanRequestCount.reset();
|
||||||
rpcServices.rpcMultiRequestCount.reset();
|
rpcServices.rpcMultiRequestCount.reset();
|
||||||
rpcServices.rpcMutateRequestCount.reset();
|
rpcServices.rpcMutateRequestCount.reset();
|
||||||
LOG.info("reportForDuty to master=" + masterServerName + " with port="
|
LOG.info("reportForDuty to master=" + masterServerName + " with port="
|
||||||
|
|
|
@ -498,6 +498,11 @@ class MetricsRegionServerWrapperImpl
|
||||||
return regionServer.rpcServices.rpcScanRequestCount.sum();
|
return regionServer.rpcServices.rpcScanRequestCount.sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getRpcFullScanRequestsCount() {
|
||||||
|
return regionServer.rpcServices.rpcFullScanRequestCount.sum();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getRpcMultiRequestsCount() {
|
public long getRpcMultiRequestsCount() {
|
||||||
return regionServer.rpcServices.rpcMultiRequestCount.sum();
|
return regionServer.rpcServices.rpcMultiRequestCount.sum();
|
||||||
|
|
|
@ -314,6 +314,9 @@ public class RSRpcServices implements HBaseRPCErrorHandler,
|
||||||
|
|
||||||
// Request counter for rpc scan
|
// Request counter for rpc scan
|
||||||
final LongAdder rpcScanRequestCount = new LongAdder();
|
final LongAdder rpcScanRequestCount = new LongAdder();
|
||||||
|
|
||||||
|
// Request counter for scans that might end up in full scans
|
||||||
|
final LongAdder rpcFullScanRequestCount = new LongAdder();
|
||||||
|
|
||||||
// Request counter for rpc multi
|
// Request counter for rpc multi
|
||||||
final LongAdder rpcMultiRequestCount = new LongAdder();
|
final LongAdder rpcMultiRequestCount = new LongAdder();
|
||||||
|
@ -459,15 +462,18 @@ public class RSRpcServices implements HBaseRPCErrorHandler,
|
||||||
private final RpcCallback shippedCallback;
|
private final RpcCallback shippedCallback;
|
||||||
private byte[] rowOfLastPartialResult;
|
private byte[] rowOfLastPartialResult;
|
||||||
private boolean needCursor;
|
private boolean needCursor;
|
||||||
|
private boolean fullRegionScan;
|
||||||
|
|
||||||
public RegionScannerHolder(String scannerName, RegionScanner s, HRegion r,
|
public RegionScannerHolder(String scannerName, RegionScanner s, HRegion r,
|
||||||
RpcCallback closeCallBack, RpcCallback shippedCallback, boolean needCursor) {
|
RpcCallback closeCallBack, RpcCallback shippedCallback, boolean needCursor,
|
||||||
|
boolean fullRegionScan) {
|
||||||
this.scannerName = scannerName;
|
this.scannerName = scannerName;
|
||||||
this.s = s;
|
this.s = s;
|
||||||
this.r = r;
|
this.r = r;
|
||||||
this.closeCallBack = closeCallBack;
|
this.closeCallBack = closeCallBack;
|
||||||
this.shippedCallback = shippedCallback;
|
this.shippedCallback = shippedCallback;
|
||||||
this.needCursor = needCursor;
|
this.needCursor = needCursor;
|
||||||
|
this.fullRegionScan = fullRegionScan;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getNextCallSeq() {
|
public long getNextCallSeq() {
|
||||||
|
@ -1326,7 +1332,7 @@ public class RSRpcServices implements HBaseRPCErrorHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
private RegionScannerHolder addScanner(String scannerName, RegionScanner s, Shipper shipper,
|
private RegionScannerHolder addScanner(String scannerName, RegionScanner s, Shipper shipper,
|
||||||
HRegion r, boolean needCursor) throws LeaseStillHeldException {
|
HRegion r, boolean needCursor, boolean fullRegionScan) throws LeaseStillHeldException {
|
||||||
Lease lease = regionServer.getLeaseManager().createLease(
|
Lease lease = regionServer.getLeaseManager().createLease(
|
||||||
scannerName, this.scannerLeaseTimeoutPeriod, new ScannerListener(scannerName));
|
scannerName, this.scannerLeaseTimeoutPeriod, new ScannerListener(scannerName));
|
||||||
RpcCallback shippedCallback = new RegionScannerShippedCallBack(scannerName, shipper, lease);
|
RpcCallback shippedCallback = new RegionScannerShippedCallBack(scannerName, shipper, lease);
|
||||||
|
@ -1336,14 +1342,30 @@ public class RSRpcServices implements HBaseRPCErrorHandler,
|
||||||
} else {
|
} else {
|
||||||
closeCallback = new RegionScannerCloseCallBack(s);
|
closeCallback = new RegionScannerCloseCallBack(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
RegionScannerHolder rsh =
|
RegionScannerHolder rsh =
|
||||||
new RegionScannerHolder(scannerName, s, r, closeCallback, shippedCallback, needCursor);
|
new RegionScannerHolder(scannerName, s, r, closeCallback, shippedCallback,
|
||||||
|
needCursor, fullRegionScan);
|
||||||
RegionScannerHolder existing = scanners.putIfAbsent(scannerName, rsh);
|
RegionScannerHolder existing = scanners.putIfAbsent(scannerName, rsh);
|
||||||
assert existing == null : "scannerId must be unique within regionserver's whole lifecycle! " +
|
assert existing == null : "scannerId must be unique within regionserver's whole lifecycle! " +
|
||||||
scannerName;
|
scannerName;
|
||||||
return rsh;
|
return rsh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isFullRegionScan(Scan scan, HRegion region) {
|
||||||
|
// If the scan start row equals or less than the start key of the region
|
||||||
|
// and stop row greater than equals end key (if stop row present)
|
||||||
|
// or if the stop row is empty
|
||||||
|
// account this as a full region scan
|
||||||
|
if (Bytes.compareTo(scan.getStartRow(), region.getRegionInfo().getStartKey()) <= 0
|
||||||
|
&& (Bytes.compareTo(scan.getStopRow(), region.getRegionInfo().getEndKey()) >= 0 &&
|
||||||
|
!Bytes.equals(region.getRegionInfo().getEndKey(), HConstants.EMPTY_END_ROW)
|
||||||
|
|| Bytes.equals(scan.getStopRow(), HConstants.EMPTY_END_ROW))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the HRegion based on a region specifier
|
* Find the HRegion based on a region specifier
|
||||||
*
|
*
|
||||||
|
@ -3164,7 +3186,12 @@ public class RSRpcServices implements HBaseRPCErrorHandler,
|
||||||
builder.setMvccReadPoint(scanner.getMvccReadPoint());
|
builder.setMvccReadPoint(scanner.getMvccReadPoint());
|
||||||
builder.setTtl(scannerLeaseTimeoutPeriod);
|
builder.setTtl(scannerLeaseTimeoutPeriod);
|
||||||
String scannerName = String.valueOf(scannerId);
|
String scannerName = String.valueOf(scannerId);
|
||||||
return addScanner(scannerName, scanner, shipper, region, scan.isNeedCursorResult());
|
|
||||||
|
boolean fullRegionScan = !region.getRegionInfo().getTable().isSystemTable() &&
|
||||||
|
isFullRegionScan(scan, region);
|
||||||
|
|
||||||
|
return addScanner(scannerName, scanner, shipper, region, scan.isNeedCursorResult(),
|
||||||
|
fullRegionScan);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkScanNextCallSeq(ScanRequest request, RegionScannerHolder rsh)
|
private void checkScanNextCallSeq(ScanRequest request, RegionScannerHolder rsh)
|
||||||
|
@ -3478,6 +3505,9 @@ public class RSRpcServices implements HBaseRPCErrorHandler,
|
||||||
}
|
}
|
||||||
throw new ServiceException(e);
|
throw new ServiceException(e);
|
||||||
}
|
}
|
||||||
|
if (rsh.fullRegionScan) {
|
||||||
|
rpcFullScanRequestCount.increment();
|
||||||
|
}
|
||||||
HRegion region = rsh.r;
|
HRegion region = rsh.r;
|
||||||
String scannerName = rsh.scannerName;
|
String scannerName = rsh.scannerName;
|
||||||
LeaseManager.Lease lease;
|
LeaseManager.Lease lease;
|
||||||
|
|
|
@ -317,4 +317,4 @@ public interface RegionServerServices extends Server, MutableOnlineRegions, Favo
|
||||||
* @return {@link ZKPermissionWatcher}
|
* @return {@link ZKPermissionWatcher}
|
||||||
*/
|
*/
|
||||||
ZKPermissionWatcher getZKPermissionWatcher();
|
ZKPermissionWatcher getZKPermissionWatcher();
|
||||||
}
|
}
|
||||||
|
|
|
@ -629,4 +629,9 @@ public class MetricsRegionServerWrapperStub implements MetricsRegionServerWrappe
|
||||||
public long getAverageRegionSize() {
|
public long getAverageRegionSize() {
|
||||||
return 10000000;
|
return 10000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getRpcFullScanRequestsCount() {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.hadoop.hbase.regionserver;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||||
|
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
||||||
|
import org.apache.hadoop.hbase.HConstants;
|
||||||
|
import org.apache.hadoop.hbase.MiniHBaseCluster.MiniHBaseClusterRegionServer;
|
||||||
|
import org.apache.hadoop.hbase.TableName;
|
||||||
|
import org.apache.hadoop.hbase.client.Put;
|
||||||
|
import org.apache.hadoop.hbase.client.Result;
|
||||||
|
import org.apache.hadoop.hbase.client.ResultScanner;
|
||||||
|
import org.apache.hadoop.hbase.client.Scan;
|
||||||
|
import org.apache.hadoop.hbase.client.Table;
|
||||||
|
import org.apache.hadoop.hbase.client.TestClientScannerRPCTimeout;
|
||||||
|
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||||
|
import org.apache.hadoop.hbase.testclassification.RegionServerTests;
|
||||||
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.experimental.categories.Category;
|
||||||
|
import org.junit.rules.TestName;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Category({ RegionServerTests.class, MediumTests.class})
|
||||||
|
public class TestScannerRPCScanMetrics {
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static final HBaseClassTestRule CLASS_RULE =
|
||||||
|
HBaseClassTestRule.forClass(TestScannerRPCScanMetrics.class);
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(TestScannerRPCScanMetrics.class);
|
||||||
|
private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
|
||||||
|
private static final byte[] FAMILY = Bytes.toBytes("testFamily");
|
||||||
|
private static final byte[] QUALIFIER = Bytes.toBytes("testQualifier");
|
||||||
|
private static final byte[] VALUE = Bytes.toBytes("testValue");
|
||||||
|
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public TestName name = new TestName();
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setupBeforeClass() throws Exception {
|
||||||
|
Configuration conf = TEST_UTIL.getConfiguration();
|
||||||
|
conf.setStrings(HConstants.REGION_SERVER_IMPL, RegionServerWithScanMetrics.class.getName());
|
||||||
|
TEST_UTIL.startMiniCluster(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void tearDownAfterClass() throws Exception {
|
||||||
|
TEST_UTIL.shutdownMiniCluster();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testScannerRPCScanMetrics() throws Exception {
|
||||||
|
final TableName tableName = TableName.valueOf(name.getMethodName());
|
||||||
|
byte[][] splits = new byte[1][];
|
||||||
|
splits[0] = Bytes.toBytes("row-4");
|
||||||
|
Table ht = TEST_UTIL.createTable(tableName, FAMILY,splits);
|
||||||
|
byte[] r0 = Bytes.toBytes("row-0");
|
||||||
|
byte[] r1 = Bytes.toBytes("row-1");
|
||||||
|
byte[] r2 = Bytes.toBytes("row-2");
|
||||||
|
byte[] r3 = Bytes.toBytes("row-3");
|
||||||
|
putToTable(ht, r0);
|
||||||
|
putToTable(ht, r1);
|
||||||
|
putToTable(ht, r2);
|
||||||
|
putToTable(ht, r3);
|
||||||
|
LOG.info("Wrote our four table entries");
|
||||||
|
Scan scan1 = new Scan();
|
||||||
|
scan1.withStartRow(r0);
|
||||||
|
// This scan should not increment rpc full scan count (start row specified)
|
||||||
|
scan1.withStopRow(Bytes.toBytes("row-4"));
|
||||||
|
scanNextIterate(ht, scan1);
|
||||||
|
Scan scan2 = new Scan();
|
||||||
|
scan2.withStartRow(r1);
|
||||||
|
// This scan should increment rpc full scan count by 1 (for second region only)
|
||||||
|
scanNextIterate(ht, scan2);
|
||||||
|
Scan scan3 = new Scan();
|
||||||
|
scan3.withStopRow(Bytes.toBytes("row-5"));
|
||||||
|
// This scan should increment rpc full scan count by 1 (for firts region only)
|
||||||
|
scanNextIterate(ht, scan3);
|
||||||
|
Scan scan4 = new Scan();
|
||||||
|
scan4.withStartRow(r1);
|
||||||
|
scan4.withStopRow(r2);
|
||||||
|
// This scan should not increment rpc full scan count (both start and stop row)
|
||||||
|
scanNextIterate(ht, scan4);
|
||||||
|
Scan dummyScan = new Scan();
|
||||||
|
// This scan should increment rpc full scan count by 2 (both regions - no stop/start row)
|
||||||
|
scanNextIterate(ht, dummyScan);
|
||||||
|
|
||||||
|
RSRpcServices testClusterRSRPCServices = TEST_UTIL.getMiniHBaseCluster().getRegionServer(0)
|
||||||
|
.rpcServices;
|
||||||
|
assertEquals(4, testClusterRSRPCServices.rpcFullScanRequestCount.intValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void putToTable(Table ht, byte[] rowkey) throws IOException {
|
||||||
|
Put put = new Put(rowkey);
|
||||||
|
put.addColumn(FAMILY, QUALIFIER, VALUE);
|
||||||
|
ht.put(put);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scanNextIterate(Table ht, Scan scan) throws Exception{
|
||||||
|
ResultScanner scanner = ht.getScanner(scan);
|
||||||
|
for (Result result = scanner.next(); result != null; result = scanner.next())
|
||||||
|
{
|
||||||
|
// Use the result object
|
||||||
|
}
|
||||||
|
scanner.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class RegionServerWithScanMetrics extends MiniHBaseClusterRegionServer {
|
||||||
|
public RegionServerWithScanMetrics(Configuration conf)
|
||||||
|
throws IOException, InterruptedException {
|
||||||
|
super(conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected RSRpcServices createRPCServices() throws IOException {
|
||||||
|
return new RSRPCServicesWithScanMetrics(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static class RSRPCServicesWithScanMetrics extends RSRpcServices {
|
||||||
|
public long getScanRequestCount() {
|
||||||
|
return super.rpcScanRequestCount.longValue();
|
||||||
|
}
|
||||||
|
public long getFullScanRequestCount() {
|
||||||
|
return super.rpcFullScanRequestCount.longValue();
|
||||||
|
}
|
||||||
|
public RSRPCServicesWithScanMetrics(HRegionServer rs)
|
||||||
|
throws IOException {
|
||||||
|
super(rs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue