Skip to content

Commit 4d358b0

Browse files
Pankajsaintstack
authored andcommitted
HBASE-22230 REST Server drops connection on long scan
Signed-off-by: stack <[email protected]>
1 parent 1f0e43a commit 4d358b0

File tree

3 files changed

+69
-3
lines changed

3 files changed

+69
-3
lines changed

hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServlet.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ public class RESTServlet implements Constants {
4646
private final UserGroupInformation realUser;
4747
private final JvmPauseMonitor pauseMonitor;
4848

49-
static final String CLEANUP_INTERVAL = "hbase.rest.connection.cleanup-interval";
50-
static final String MAX_IDLETIME = "hbase.rest.connection.max-idletime";
49+
public static final String CLEANUP_INTERVAL = "hbase.rest.connection.cleanup-interval";
50+
public static final String MAX_IDLETIME = "hbase.rest.connection.max-idletime";
5151
static final String HBASE_REST_SUPPORT_PROXYUSER = "hbase.rest.support.proxyuser";
5252

5353
UserGroupInformation getRealUser() {
@@ -62,6 +62,13 @@ public synchronized static RESTServlet getInstance() {
6262
return INSTANCE;
6363
}
6464

65+
/**
66+
* @return the ConnectionCache instance
67+
*/
68+
public ConnectionCache getConnectionCache() {
69+
return connectionCache;
70+
}
71+
6572
/**
6673
* @param conf Existing configuration to use in rest servlet
6774
* @param userProvider the login user provider

hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/ScannerInstanceResource.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ public Response get(final @Context UriInfo uriInfo,
8282
return Response.status(Response.Status.NOT_FOUND)
8383
.type(MIMETYPE_TEXT).entity("Not found" + CRLF)
8484
.build();
85+
} else {
86+
// Updated the connection access time for each client next() call
87+
RESTServlet.getInstance().getConnectionCache().updateConnectionAccessTime();
8588
}
8689
CellSetModel model = new CellSetModel();
8790
RowModel rowModel = null;

hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteTable.java

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import org.apache.hadoop.hbase.client.Scan;
4545
import org.apache.hadoop.hbase.client.Table;
4646
import org.apache.hadoop.hbase.rest.HBaseRESTTestingUtility;
47+
import org.apache.hadoop.hbase.rest.RESTServlet;
4748
import org.apache.hadoop.hbase.testclassification.MediumTests;
4849
import org.apache.hadoop.hbase.testclassification.RestTests;
4950
import org.apache.hadoop.hbase.util.Bytes;
@@ -576,5 +577,60 @@ public void testResponse(){
576577
assertTrue(response.hasBody());
577578
}
578579

579-
}
580+
/**
581+
* Tests keeping a HBase scanner alive for long periods of time. Each call to next() should reset
582+
* the ConnectionCache timeout for the scanner's connection
583+
* @throws Exception
584+
*/
585+
@Test
586+
public void testLongLivedScan() throws Exception {
587+
int numTrials = 6;
588+
int trialPause = 1000;
589+
int cleanUpInterval = 100;
590+
591+
// Shutdown the Rest Servlet container
592+
REST_TEST_UTIL.shutdownServletContainer();
580593

594+
// Set the ConnectionCache timeout to trigger halfway through the trials
595+
TEST_UTIL.getConfiguration().setLong(RESTServlet.MAX_IDLETIME, (numTrials / 2) * trialPause);
596+
TEST_UTIL.getConfiguration().setLong(RESTServlet.CLEANUP_INTERVAL, cleanUpInterval);
597+
598+
// Start the Rest Servlet container
599+
REST_TEST_UTIL.startServletContainer(TEST_UTIL.getConfiguration());
600+
601+
// Truncate the test table for inserting test scenarios rows keys
602+
TEST_UTIL.getHBaseAdmin().disableTable(TABLE);
603+
TEST_UTIL.getHBaseAdmin().truncateTable(TABLE, false);
604+
605+
remoteTable = new RemoteHTable(
606+
new Client(new Cluster().add("localhost", REST_TEST_UTIL.getServletPort())),
607+
TEST_UTIL.getConfiguration(), TABLE.toBytes());
608+
609+
String row = "testrow";
610+
611+
try (Table table = TEST_UTIL.getConnection().getTable(TABLE)) {
612+
List<Put> puts = new ArrayList<Put>();
613+
Put put = null;
614+
for (int i = 1; i <= numTrials; i++) {
615+
put = new Put(Bytes.toBytes(row + i));
616+
put.addColumn(COLUMN_1, QUALIFIER_1, TS_2, Bytes.toBytes("testvalue" + i));
617+
puts.add(put);
618+
}
619+
table.put(puts);
620+
}
621+
622+
Scan scan = new Scan();
623+
scan.setCaching(1);
624+
scan.setBatch(1);
625+
626+
ResultScanner scanner = remoteTable.getScanner(scan);
627+
Result result = null;
628+
// get scanner and rows
629+
for (int i = 1; i <= numTrials; i++) {
630+
// Make sure that the Scanner doesn't throw an exception after the ConnectionCache timeout
631+
result = scanner.next();
632+
assertEquals(row + i, Bytes.toString(result.getRow()));
633+
Thread.sleep(trialPause);
634+
}
635+
}
636+
}

0 commit comments

Comments
 (0)