HBASE-25817 Memory leak from thrift server hashMap (#3257)

Use GuavaCache in thrift server hashmap

Signed-off-by: Michael Stack <stack@apache.org>
This commit is contained in:
sambong0113 2021-05-22 10:55:15 +09:00 committed by Duo Zhang
parent 646dbfee03
commit 0e18900c36
1 changed files with 19 additions and 7 deletions

View File

@ -19,6 +19,8 @@
package org.apache.hadoop.hbase.thrift;
import static org.apache.hadoop.hbase.HConstants.DEFAULT_HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD;
import static org.apache.hadoop.hbase.HConstants.HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD;
import static org.apache.hadoop.hbase.thrift.Constants.COALESCE_INC_KEY;
import static org.apache.hadoop.hbase.util.Bytes.getBytes;
@ -26,11 +28,10 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellBuilder;
@ -85,6 +86,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.hbase.thirdparty.com.google.common.base.Throwables;
import org.apache.hbase.thirdparty.com.google.common.cache.Cache;
import org.apache.hbase.thirdparty.com.google.common.cache.CacheBuilder;
/**
* The HBaseServiceHandler is a glue object that connects Thrift RPC calls to the
@ -99,7 +102,7 @@ public class ThriftHBaseServiceHandler extends HBaseServiceHandler implements Hb
// nextScannerId and scannerMap are used to manage scanner state
private int nextScannerId = 0;
private HashMap<Integer, ResultScannerWrapper> scannerMap;
private Cache<Integer, ResultScannerWrapper> scannerMap;
IncrementCoalescer coalescer;
/**
@ -141,7 +144,7 @@ public class ThriftHBaseServiceHandler extends HBaseServiceHandler implements Hb
* @return a Scanner, or null if ID was invalid.
*/
private synchronized ResultScannerWrapper getScanner(int id) {
return scannerMap.get(id);
return scannerMap.getIfPresent(id);
}
/**
@ -151,14 +154,19 @@ public class ThriftHBaseServiceHandler extends HBaseServiceHandler implements Hb
* @param id the ID of the scanner to remove
* @return a Scanner, or null if ID was invalid.
*/
private synchronized ResultScannerWrapper removeScanner(int id) {
return scannerMap.remove(id);
private synchronized void removeScanner(int id) {
scannerMap.invalidate(id);
}
protected ThriftHBaseServiceHandler(final Configuration c,
final UserProvider userProvider) throws IOException {
super(c, userProvider);
scannerMap = new HashMap<>();
long cacheTimeout = c.getLong(HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD, DEFAULT_HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD) * 2;
scannerMap = CacheBuilder.newBuilder()
.expireAfterAccess(cacheTimeout, TimeUnit.MILLISECONDS)
.build();
this.coalescer = new IncrementCoalescer(this);
}
@ -863,6 +871,10 @@ public class ThriftHBaseServiceHandler extends HBaseServiceHandler implements Hb
} catch (IOException e) {
LOG.warn(e.getMessage(), e);
throw getIOError(e);
} finally {
// Add scanner back to scannerMap; protects against case
// where scanner expired during processing of request.
scannerMap.put(id, resultScannerWrapper);
}
return ThriftUtilities.rowResultFromHBase(results, resultScannerWrapper.isColumnSorted());
}