-
Notifications
You must be signed in to change notification settings - Fork 4.8k
HIVE-29620: RetryingMetaStoreClient uses HiveMetaStoreClientBuilder t… #6499
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,9 +33,11 @@ | |
| import java.util.concurrent.TimeUnit; | ||
| import java.util.function.Supplier; | ||
|
|
||
| import org.apache.commons.lang3.ClassUtils; | ||
| import org.apache.hadoop.classification.InterfaceAudience; | ||
| import org.apache.hadoop.conf.Configuration; | ||
| import org.apache.hadoop.hive.common.classification.RetrySemantics; | ||
| import org.apache.hadoop.hive.metastore.client.builder.HiveMetaStoreClientBuilder; | ||
| import org.apache.hadoop.hive.metastore.conf.MetastoreConf; | ||
| import org.apache.hadoop.hive.metastore.conf.MetastoreConf.ConfVars; | ||
| import org.apache.hadoop.hive.metastore.utils.JavaUtils; | ||
|
|
@@ -69,15 +71,7 @@ public class RetryingMetaStoreClient implements InvocationHandler { | |
| private final Map<String, Long> metaCallTimeMap; | ||
| private final long connectionLifeTimeInMillis; | ||
| private long lastConnectionTime; | ||
| private boolean localMetaStore; | ||
|
|
||
|
|
||
| protected RetryingMetaStoreClient(Configuration conf, Class<?>[] constructorArgTypes, | ||
| Object[] constructorArgs, Map<String, Long> metaCallTimeMap, | ||
| Class<? extends IMetaStoreClient> msClientClass) throws MetaException { | ||
| this(conf, metaCallTimeMap, () -> | ||
| JavaUtils.newInstance(msClientClass, constructorArgTypes, constructorArgs)); | ||
| } | ||
| private final boolean localMetaStore; | ||
|
|
||
| protected RetryingMetaStoreClient(Configuration conf, Map<String, Long> metaCallTimeMap, | ||
| Supplier<? extends IMetaStoreClient> msClient) throws MetaException { | ||
|
|
@@ -95,12 +89,11 @@ protected RetryingMetaStoreClient(Configuration conf, Map<String, Long> metaCall | |
| this.connectionLifeTimeInMillis = MetastoreConf.getTimeVar(conf, | ||
| ConfVars.CLIENT_SOCKET_LIFETIME, TimeUnit.MILLISECONDS); | ||
| this.lastConnectionTime = System.currentTimeMillis(); | ||
| String msUri = MetastoreConf.getVar(conf, ConfVars.THRIFT_URIS); | ||
| localMetaStore = (msUri == null) || msUri.trim().isEmpty(); | ||
|
|
||
| SecurityUtils.reloginExpiringKeytabUser(); | ||
|
|
||
| this.base = msClient.get(); | ||
| this.localMetaStore = base.isLocalMetaStore(); | ||
|
|
||
| LOG.info("RetryingMetaStoreClient proxy=" + base.getClass() + " ugi=" + this.ugi | ||
| + " retries=" + this.retryLimit + " delay=" + this.retryDelaySeconds | ||
|
|
@@ -109,9 +102,7 @@ protected RetryingMetaStoreClient(Configuration conf, Map<String, Long> metaCall | |
|
|
||
| public static IMetaStoreClient getProxy( | ||
| Configuration hiveConf, boolean allowEmbedded) throws MetaException { | ||
| return getProxy(hiveConf, new Class[]{Configuration.class, HiveMetaHookLoader.class, Boolean.class}, | ||
| new Object[]{hiveConf, null, allowEmbedded}, null, HiveMetaStoreClient.class.getName() | ||
| ); | ||
| return new HiveMetaStoreClientBuilder(hiveConf, allowEmbedded).withRetry(null).build(); | ||
| } | ||
|
|
||
| @VisibleForTesting | ||
|
|
@@ -123,13 +114,14 @@ public static IMetaStoreClient getProxy(Configuration hiveConf, HiveMetaHookLoad | |
| public static IMetaStoreClient getProxy(Configuration hiveConf, HiveMetaHookLoader hookLoader, | ||
| Map<String, Long> metaCallTimeMap, String mscClassName, boolean allowEmbedded) | ||
| throws MetaException { | ||
|
|
||
| return getProxy(hiveConf, | ||
| new Class[] {Configuration.class, HiveMetaHookLoader.class, Boolean.class}, | ||
| new Object[] {hiveConf, hookLoader, allowEmbedded}, | ||
| metaCallTimeMap, | ||
| mscClassName | ||
| ); | ||
| String origClientImpl = MetastoreConf.getVar(hiveConf, ConfVars.METASTORE_CLIENT_IMPL); | ||
| try { | ||
| MetastoreConf.setVar(hiveConf, ConfVars.METASTORE_CLIENT_IMPL, mscClassName); | ||
| return new HiveMetaStoreClientBuilder(hiveConf, allowEmbedded) | ||
| .withHooks(hookLoader).withRetry(metaCallTimeMap).build(); | ||
| } finally { | ||
| MetastoreConf.setVar(hiveConf, ConfVars.METASTORE_CLIENT_IMPL, origClientImpl); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same, this looks like a hack |
||
| } | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -148,26 +140,18 @@ public static IMetaStoreClient getProxy(Configuration hiveConf, Class<?>[] const | |
| public static IMetaStoreClient getProxy(Configuration hiveConf, Class<?>[] constructorArgTypes, | ||
| Object[] constructorArgs, Map<String, Long> metaCallTimeMap, | ||
| String mscClassName) throws MetaException { | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| Class<? extends IMetaStoreClient> baseClass = | ||
| JavaUtils.getClass(mscClassName, IMetaStoreClient.class); | ||
|
|
||
| RetryingMetaStoreClient handler = | ||
| new RetryingMetaStoreClient(hiveConf, constructorArgTypes, constructorArgs, | ||
| metaCallTimeMap, baseClass); | ||
| return getProxy(baseClass.getInterfaces(), handler); | ||
| IMetaStoreClient baseClient = JavaUtils.newInstance(baseClass, constructorArgTypes, constructorArgs); | ||
| return new HiveMetaStoreClientBuilder(hiveConf, baseClient).withRetry(metaCallTimeMap).build(); | ||
| } | ||
|
|
||
| public static IMetaStoreClient getProxy(Configuration hiveConf, Map<String, Long> metaCallTimeMap, | ||
| IMetaStoreClient msClient) throws MetaException { | ||
| RetryingMetaStoreClient handler = | ||
| new RetryingMetaStoreClient(hiveConf, metaCallTimeMap, () -> msClient); | ||
| return getProxy(msClient.getClass().getInterfaces(), handler); | ||
| } | ||
|
|
||
| private static IMetaStoreClient getProxy(Class<?>[] interfaces, | ||
| RetryingMetaStoreClient handler) { | ||
| Class<?>[] interfaces = ClassUtils.getAllInterfaces(msClient.getClass()).toArray(new Class[0]); | ||
| return (IMetaStoreClient) Proxy.newProxyInstance( | ||
| RetryingMetaStoreClient.class.getClassLoader(), interfaces, handler); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,11 +36,11 @@ | |
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
||
| public abstract class MetaStoreClientWrapper extends BaseMetaStoreClient { | ||
| public abstract class FilterMetaStoreClient extends BaseMetaStoreClient { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what does it filter ?? |
||
|
|
||
| protected final IMetaStoreClient delegate; | ||
|
|
||
| public MetaStoreClientWrapper(IMetaStoreClient delegate, Configuration conf) { | ||
| public FilterMetaStoreClient(IMetaStoreClient delegate, Configuration conf) { | ||
| super(conf); | ||
| this.delegate = delegate; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,41 +19,49 @@ | |
| package org.apache.hadoop.hive.metastore.client.builder; | ||
|
|
||
| import org.apache.commons.lang3.exception.ExceptionUtils; | ||
| import org.apache.commons.lang3.reflect.ConstructorUtils; | ||
| import org.apache.commons.lang3.tuple.Pair; | ||
| import org.apache.hadoop.conf.Configuration; | ||
| import org.apache.hadoop.hive.metastore.HiveMetaHookLoader; | ||
| import org.apache.hadoop.hive.metastore.HiveMetaStoreClient; | ||
| import org.apache.hadoop.hive.metastore.IMetaStoreClient; | ||
| import org.apache.hadoop.hive.metastore.RetryingMetaStoreClient; | ||
| import org.apache.hadoop.hive.metastore.api.MetaException; | ||
| import org.apache.hadoop.hive.metastore.client.HookEnabledMetaStoreClient; | ||
| import org.apache.hadoop.hive.metastore.client.SynchronizedMetaStoreClient; | ||
| import org.apache.hadoop.hive.metastore.client.ThriftHiveMetaStoreClient; | ||
| import org.apache.hadoop.hive.metastore.conf.MetastoreConf; | ||
| import org.apache.hadoop.hive.metastore.utils.JavaUtils; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
||
| import java.lang.reflect.Constructor; | ||
| import java.util.Map; | ||
| import java.util.Objects; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
| import java.util.function.Function; | ||
|
|
||
| public class HiveMetaStoreClientBuilder { | ||
| private static final Logger LOG = LoggerFactory.getLogger(HiveMetaStoreClientBuilder.class); | ||
| private static final Map<Class<? extends IMetaStoreClient>, MetaStoreClientFactory> | ||
| CLIENT_FACTORIES = new ConcurrentHashMap<>(); | ||
|
|
||
| private final Configuration conf; | ||
| private IMetaStoreClient client; | ||
|
|
||
| public HiveMetaStoreClientBuilder(Configuration conf) { | ||
| this.conf = Objects.requireNonNull(conf); | ||
| } | ||
|
|
||
| public HiveMetaStoreClientBuilder newClient(boolean allowEmbedded) throws MetaException { | ||
| public HiveMetaStoreClientBuilder(Configuration configuration, boolean allowEmbedded) throws MetaException { | ||
| this.conf = new Configuration(Objects.requireNonNull(configuration)); | ||
| boolean isHiveClient = HiveMetaStoreClient.class.getName().equals( | ||
| MetastoreConf.getVar(conf, MetastoreConf.ConfVars.METASTORE_CLIENT_IMPL)); | ||
| if (isHiveClient) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this looks like a hack |
||
| // Prevent stack overflow as HiveMetaStoreClient calls HiveMetaStoreClientBuilder to build the underlying client | ||
| MetastoreConf.setVar(conf, MetastoreConf.ConfVars.METASTORE_CLIENT_IMPL, ThriftHiveMetaStoreClient.class.getName()); | ||
| } | ||
| this.client = createClient(conf, allowEmbedded); | ||
| return this; | ||
| } | ||
|
|
||
| public HiveMetaStoreClientBuilder client(IMetaStoreClient client) { | ||
| this.client = client; | ||
| return this; | ||
| public HiveMetaStoreClientBuilder(Configuration conf, IMetaStoreClient client) { | ||
| this.conf = Objects.requireNonNull(conf); | ||
| this.client = Objects.requireNonNull(client); | ||
| } | ||
|
|
||
| public HiveMetaStoreClientBuilder enhanceWith(Function<IMetaStoreClient, IMetaStoreClient> wrapperFunction) { | ||
|
|
@@ -81,16 +89,16 @@ public IMetaStoreClient build() { | |
| } | ||
|
|
||
| private static IMetaStoreClient createClient(Configuration conf, boolean allowEmbedded) throws MetaException { | ||
| Class<? extends IMetaStoreClient> mscClass = MetastoreConf.getClass( | ||
| conf, MetastoreConf.ConfVars.METASTORE_CLIENT_IMPL, | ||
| ThriftHiveMetaStoreClient.class, IMetaStoreClient.class); | ||
| LOG.info("Using {} as a base MetaStoreClient", mscClass.getName()); | ||
|
|
||
| IMetaStoreClient baseMetaStoreClient = null; | ||
| try { | ||
| baseMetaStoreClient = JavaUtils.newInstance(mscClass, | ||
| new Class[]{Configuration.class, boolean.class}, | ||
| new Object[]{conf, allowEmbedded}); | ||
| Class<? extends IMetaStoreClient> mscClass = MetastoreConf.getClass( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do you need mscClass under try-catch block? |
||
| conf, MetastoreConf.ConfVars.METASTORE_CLIENT_IMPL, | ||
| ThriftHiveMetaStoreClient.class, IMetaStoreClient.class); | ||
| LOG.info("Using {} as a base MetaStoreClient", mscClass.getName()); | ||
| MetaStoreClientFactory factory = CLIENT_FACTORIES.get(mscClass); | ||
| if (factory == null) { | ||
| CLIENT_FACTORIES.put(mscClass, factory = new MetaStoreClientFactory(mscClass)); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do you initiate CLIENT_FACTORIES inside createClient ? that doesn't seem a good design |
||
| } | ||
| return factory.createClient(conf, allowEmbedded); | ||
| } catch (Throwable t) { | ||
| // Reflection by JavaUtils will throw RuntimeException, try to get real MetaException here. | ||
| Throwable rootCause = ExceptionUtils.getRootCause(t); | ||
|
|
@@ -100,7 +108,34 @@ private static IMetaStoreClient createClient(Configuration conf, boolean allowEm | |
| throw new MetaException(rootCause.getMessage()); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private static class MetaStoreClientFactory { | ||
| private Constructor<? extends IMetaStoreClient> bestMatchingCtr; | ||
| private Function<Pair<Configuration, Boolean>, Object[]> argsTransformer; | ||
|
|
||
| MetaStoreClientFactory(Class<? extends IMetaStoreClient> mscClass) { | ||
| Constructor<? extends IMetaStoreClient> candidate = | ||
| ConstructorUtils.getMatchingAccessibleConstructor(mscClass, Configuration.class, boolean.class); | ||
| if (candidate != null) { | ||
| this.bestMatchingCtr = candidate; | ||
| this.argsTransformer = args -> new Object[] {args.getLeft(), (boolean) args.getRight()}; | ||
| } else if ((candidate = ConstructorUtils.getMatchingAccessibleConstructor(mscClass, Configuration.class, | ||
| HiveMetaHookLoader.class, Boolean.class)) != null) { | ||
| this.bestMatchingCtr = candidate; | ||
| this.argsTransformer = args -> | ||
| new Object[] {args.getLeft(), null, Boolean.valueOf(args.getRight())}; | ||
| } else if ((candidate = ConstructorUtils.getMatchingAccessibleConstructor(mscClass, Configuration.class)) != null) { | ||
| this.bestMatchingCtr = candidate; | ||
| this.argsTransformer = args -> new Object[] {args.getLeft()}; | ||
| } | ||
| if (bestMatchingCtr == null) { | ||
| throw new RuntimeException("No matching constructor found for this IMetaStoreClient " + mscClass); | ||
| } | ||
| } | ||
|
|
||
| return baseMetaStoreClient; | ||
| IMetaStoreClient createClient(Configuration conf, boolean allowEmbedded) throws Exception { | ||
| return bestMatchingCtr.newInstance(argsTransformer.apply(Pair.of(conf, allowEmbedded))); | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we really need to specify
withRetry(null)?