Este artigo descreve minha pequena aventura em torno de um erro de inicialização com o Hive Metastore. Deve ser reproduzível com qualquer instalação segura, ou seja, com Kerberos, com alta disponibilidade ativada e com o armazenamento do token de delegação em um banco de dados. A versão do Hive é o 1.2 embalado dentro da distribuição Hortonworks 2.4.2.
O armazenamento para o token de delegação é definido pelo hive.cluster.delegation.token.store.class
propriedade. As opções disponíveis são o Zookeeper, o banco de dados e a memória da Metastore. Cloudera e Hortonworks recomendam usar o banco de dados como org.apache.hadoop.hive.thrift.DBTokenStore
.
O erro em questão ocorre no lançamento da Metastore e leva a seguinte assinatura:
java.io.IOException: Failed to initialize master key
at org.apache.hadoop.hive.thrift.TokenStoreDelegationTokenSecretManager.startThreads(TokenStoreDelegationTokenSecretManager.java:213)
at org.apache.hadoop.hive.thrift.HiveDelegationTokenManager.startDelegationTokenSecretManager(HiveDelegationTokenManager.java:96)
at org.apache.hadoop.hive.metastore.HiveMetaStore.startMetaStore(HiveMetaStore.java:6031)
at org.apache.hadoop.hive.metastore.HiveMetaStore.main(HiveMetaStore.java:5945)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.util.RunJar.run(RunJar.java:221)
at org.apache.hadoop.util.RunJar.main(RunJar.java:136)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.hive.thrift.TokenStoreDelegationTokenSecretManager.startThreads(TokenStoreDelegationTokenSecretManager.java:211)
... 9 more
Caused by: org.apache.hadoop.hive.thrift.DelegationTokenStore$TokenStoreException: java.lang.NoSuchMethodException: org.apache.hadoop.hive.metastore.HiveMetaStore$HMSHandler.addMasterKey(java.lang.String)
at org.apache.hadoop.hive.thrift.DBTokenStore.invokeOnRawStore(DBTokenStore.java:158)
at org.apache.hadoop.hive.thrift.DBTokenStore.addMasterKey(DBTokenStore.java:42)
at org.apache.hadoop.hive.thrift.TokenStoreDelegationTokenSecretManager.logUpdateMasterKey(TokenStoreDelegationTokenSecretManager.java:193)
at org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager.updateCurrentKey(AbstractDelegationTokenSecretManager.java:335)
... 14 more
Caused by: java.lang.NoSuchMethodException: org.apache.hadoop.hive.metastore.HiveMetaStore$HMSHandler.addMasterKey(java.lang.String)
at java.lang.Class.getMethod(Class.java:1670)
at org.apache.hadoop.hive.thrift.DBTokenStore.invokeOnRawStore(DBTokenStore.java:148)
... 17 more
Exception in thread "main" java.io.IOException: Failed to initialize master key
at org.apache.hadoop.hive.thrift.TokenStoreDelegationTokenSecretManager.startThreads(TokenStoreDelegationTokenSecretManager.java:213)
at org.apache.hadoop.hive.thrift.HiveDelegationTokenManager.startDelegationTokenSecretManager(HiveDelegationTokenManager.java:96)
at org.apache.hadoop.hive.metastore.HiveMetaStore.startMetaStore(HiveMetaStore.java:6031)
at org.apache.hadoop.hive.metastore.HiveMetaStore.main(HiveMetaStore.java:5945)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.util.RunJar.run(RunJar.java:221)
at org.apache.hadoop.util.RunJar.main(RunJar.java:136)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.hive.thrift.TokenStoreDelegationTokenSecretManager.startThreads(TokenStoreDelegationTokenSecretManager.java:211)
... 9 more
Caused by: org.apache.hadoop.hive.thrift.DelegationTokenStore$TokenStoreException: java.lang.NoSuchMethodException: org.apache.hadoop.hive.metastore.HiveMetaStore$HMSHandler.addMasterKey(java.lang.String)
at org.apache.hadoop.hive.thrift.DBTokenStore.invokeOnRawStore(DBTokenStore.java:158)
at org.apache.hadoop.hive.thrift.DBTokenStore.addMasterKey(DBTokenStore.java:42)
at org.apache.hadoop.hive.thrift.TokenStoreDelegationTokenSecretManager.logUpdateMasterKey(TokenStoreDelegationTokenSecretManager.java:193)
at org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager.updateCurrentKey(AbstractDelegationTokenSecretManager.java:335)
... 14 more
Caused by: java.lang.NoSuchMethodException: org.apache.hadoop.hive.metastore.HiveMetaStore$HMSHandler.addMasterKey(java.lang.String)
at java.lang.Class.getMethod(Class.java:1670)
at org.apache.hadoop.hive.thrift.DBTokenStore.invokeOnRawStore(DBTokenStore.java:148)
... 17 more
A mensagem impressa no stdout é bastante clara:
java.io.IOException: Failed to initialize master key Caused by: org.apache.hadoop.hive.thrift.DelegationTokenStore$TokenStoreException: java.lang.NoSuchMethodException: org.apache.hadoop.hive.metastore.HiveMetaStore$HMSHandler.addMasterKey
Vamos mergulhar no código -fonte. A Hortonworks publica no GitHub o código -fonte de todos os componentes de sua distribuição. Cada versão de distribuição corresponde a uma tag associada no Git. Hive para HDP 2.4.2 pode ser importado para nossa estação de trabalho local com os comandos (o link agora está quebrado porque o ramo foi apagado por Cloudera):
git clone https://github.com/hortonworks/hive-release/blob/HDP-2.4.2.0-tag
git checkout HDP-2.4.2.0-tag
De fato, não há função Hivemettore $ hmshandler.addmasterKey (editar: a fonte não está mais disponível) na versão 2.4.2. Podemos encontrar exatamente a mesma função dentro da classe ObjectStore (Editar: Origem não mais disponível) do mesmo pacote. Na versão 1.3 do Hive, como na versão 2.1, o código não parecia ter mudado. Nos logs, confirmamos que é a classe ObjectStore que é mencionada:
metastore.HiveMetaStore - 0: Opening raw store with implemenation class:org.apache.hadoop.hive.metastore.ObjectStore
Portanto, do ponto de vista da configuração, o parâmetro é bem transmitido a partir da configuração e tudo deve estar ok. O erro é chamado na Linha 42 da Classe DBTOKENSORE (Editar: Fonte não está mais disponível) pelo código:
return (Integer)invokeOnRawStore("addMasterKey", new Object[]{s},String.class);
Então, novamente, na linha 156 (editar: a fonte não está mais disponível) com o código:
return rawStore.getClass().getMethod(methName, paramTypes).invoke(rawStore, params)
Então, vamos descobrir como rawStore
é construído:
- chega através do
DBTokenStore.init
método - não tenho muita certeza de onde o init é chamado
- Mas depois de uma pesquisa rápida,
objectStore
é instanciado emHiveAuthFactory
porrawStore = baseHandler.getMS ();
ondebaseHandler
éHiveMetaStore.HMSHandler
- em
HiveMetaStore.HMSHandler.getMS
ogetMS
Método retorna uma instância dethreadLocalMS.get()
ou newrawstore () senull
- em
- esta última,
newRawStore
alimenta -se dorawStoreClassName
propriedade - Esta propriedade é inicializada a partir da configuração (editar: fonte não está mais disponível)
rawStoreClassName = hiveConf.getVar(HiveConf.ConfVars.METASTORE_RAW_STORE_IMPL);
- O valor padrão dele é declarado no HiveConf (editar: fonte não está mais disponível)
METASTORE_RAW_STORE_IMPL
(“Hive.metastore.rawstore.impl”, “org.apache.hadoop.hive.metastore.objecttore”,…) - Voltamos à aula
ObjectStore
que contém nosso métodogetMasterKey
então o que está acontecendo?
Ao re-carimbar o código-fonte, vemos que HiveAuthFactory
onde rawstore
é construído e passado para a função startDelegationTokenSecretManager
aplica -se ao HiveServer2. Hmm, poderia haver um equivalente para a Metastore?
Uma pesquisa com startDelegationTokenSecretManager
nos leva novamente ao Hivemetastore. E uma vez lá, o que podemos ler:
delegationTokenManager.startDelegationTokenSecretManager(
conf, baseHandler, ServerMode.METASTORE);
Com baseHandler
sendo instanciado um pouco acima pelo código:
HMSHandler baseHandler = new HiveMetaStore.HMSHandler(
"new db based metaserver", conf, false);
A assinatura de startDelegationTokenSecretManager
é:
public void startDelegationTokenSecretManager(Configuration conf, Object hms, ServerMode smode) throws IOException
Qualquer objeto pode ser passado como um segundo argumento que é lógico, pois o Hive está usando a reflexão.
Inspirado por HiveAuthFactory
podemos ver como rawStore
é obtido de baseHandler
. Então o parâmetro não é baseHandler
mas baseHandler.getMS ()
.
Portanto, o Hivemetastore na linha 6031 (editar: a fonte não está mais disponível) deve parecer:
delegationTokenManager.startDelegationTokenSecretManager(conf, baseHandler.getMS(), ServerMode.METASTORE);
Depois que a modificação é aplicada, agora é hora de compilar tudo isso.
O comando mvn clean package -DskipTests -Phadoop-2
não está trabalhando na primeira tentativa. Isso realmente não poderia acontecer. Estando interessado apenas na compilação do frasco associado à Metastore, tenhamos a opção de corrigir rapidamente os erros de compilação. Felizmente, haverá apenas um. Consiste em remover todas as referências à classe CallerContext
No Hadoop23Shims (editar: a fonte não está mais disponível). Depois disso, o MAVEN não compila todos os projetos, mas vai longe o suficiente para gerar o frasco da Metastore.
Em termos de implantação, tudo também não é tão simples. Substituir o frasco em questão não é suficiente porque outro frasco carregado anteriormente também contém as classes impactadas. Tomei a solução para reescrever a variável do ambiente HADOOP_CLASSPATH
Ao prefixá -lo com nosso frasco recém -importado. No arquivo “/usr/hdp/current/hive-metastore/bin/ext/metastore.sh”, add:
export HADOOP_CLASSPATH="/usr/hdp/2.4.2.0-258/hive/lib/hive-metastore.jar:$HADOOP_CLASSPATH"
Antes da linha:
export HADOOP_OPTS="$HIVE_METASTORE_HADOOP_OPTS $HADOOP_OPTS"
Agora você pode executar o comando hive --service metastore
e a Metastore deve começar.
No momento da redação deste artigo, parece que esse problema ainda está presente no ramo principal da Metastore Hive quando este artigo foi escrito. No entanto, não estava presente no lançamento anterior HDP 2.4.0 (editar: a fonte não está mais disponível).
ATUALIZAR: Os links no artigo podem ser quebrados.