Existem várias maneiras de acessar e interagir com o Apache HBase. Mais notavelmente, a API Java fornece mais funcionalidades. Mas algumas pessoas querem usar o HBase sem Java.
Essas pessoas têm duas opções principais:uma é a interface Thrift (a mais leve e, portanto, mais rápida das duas opções), e a outra é a interface REST (aka Stargate). Uma interface REST usa verbos HTTP para executar uma ação. Ao usar HTTP, uma interface REST oferece uma gama muito maior de linguagens e programas que podem acessar a interface. (Se você quiser mais informações sobre a interface REST, você pode ir para minha série de instruções sobre isso.)
Nesta série de instruções, você aprenderá a usar a interface do Thrift e explorará exemplos de código Python para fazer isso. Esta primeira postagem abordará o HBase Thrift, trabalhando com o Thrift, e algum código clichê para conectar-se ao Thrift. A segunda postagem mostrará como inserir e obter várias linhas ao mesmo tempo. O terceiro post explicará como usar scans e algumas considerações ao escolher entre REST e Thrift.
Os exemplos de código completos podem ser encontrados na minha conta do GitHub.
HBase Thrift
Thrift é uma estrutura de software que permite criar ligações entre linguagens. No contexto do HBase, Java é o único cidadão de primeira classe. No entanto, a interface do HBase Thrift permite que outros idiomas acessem o HBase sobre Thrift conectando-se a um servidor Thrift que faz interface com o cliente Java.
Para que o Thrift e o REST funcionem, outro daemon do HBase precisa estar em execução para lidar com essas solicitações. Esses daemons podem ser instalados com os pacotes hbase-thrift e hbase-rest. O diagrama abaixo mostra como Thrift e REST são colocados no cluster.
Observe que os hosts do cliente Thrift e REST geralmente não executam nenhum outro serviço (como DataNodes ou RegionServers) para manter a sobrecarga baixa e a capacidade de resposta alta para interações REST ou Thrift.
Certifique-se de instalar e iniciar esses daemons em nós que têm acesso ao cluster Hadoop e ao aplicativo que precisa de acesso ao HBase. A interface do Thrift não possui nenhum balanceamento de carga integrado, portanto, todo o balanceamento de carga precisará ser feito com ferramentas externas, como DNS round-robin, um endereço IP virtual ou em código. O Cloudera Manager também facilita muito a instalação e o gerenciamento dos serviços HBase REST e Thrift. Você pode baixar e experimentar gratuitamente no Cloudera Standard!
A desvantagem do Thrift é que é mais difícil de configurar do que o REST. Você precisará compilar o Thrift e gerar as ligações específicas do idioma. Essas ligações são boas porque fornecem código para a linguagem em que você está trabalhando — não há necessidade de analisar XML ou JSON como em REST; em vez disso, a interface do Thrift oferece acesso direto aos dados da linha. Outro recurso interessante é que o protocolo Thrift possui transporte binário nativo; você não precisará codificar e decodificar dados em base64.
Para começar a usar a interface do Thrift, você precisa descobrir em qual porta ela está sendo executada. A porta padrão para CDH é a porta 9090. Para esta postagem, você verá as variáveis de host e porta usadas, aqui estão os valores que usaremos:
host ="localhost"port ="9090"
Você pode configurar a interface do Thrift para usar as credenciais do Kerberos para maior segurança.
Para seu código, você precisará usar o endereço IP ou o nome de domínio totalmente qualificado do nó e a porta que executa o daemon Thrift. É altamente recomendável tornar essa URL uma variável, pois ela pode mudar com as alterações da rede.
Vinculações de idioma
Antes de criar ligações do Thrift, você deve baixar e compilar o Thrift. Não há pacotes binários para o Thrift que eu possa encontrar, exceto no Windows. Você terá que seguir as instruções da Thrift para a instalação na plataforma de sua escolha.
Uma vez instalado o Thrift, você precisa encontrar o arquivo Hbase.thrift. Para definir os serviços e tipos de dados no Thrift, você precisa criar um arquivo IDL. Felizmente, os desenvolvedores do HBase já criaram um para nós. Infelizmente, o arquivo não é distribuído como parte dos pacotes binários do CDH. (Vamos corrigir isso em uma versão futura do CDH.) Você precisará baixar o pacote de origem da versão do HBase que está usando. Certifique-se de usar a versão correta do HBase, pois esse IDL pode mudar. No arquivo compactado, o caminho para o IDL é hbase-VERSION/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift.
Thrift suporta a geração de ligações de linguagem para mais de 14 linguagens, incluindo Java, C++, Python, PHP, Ruby e C#. Para gerar as ligações para Python, você usaria o seguinte comando:
thrift -gen py /path/to/hbase/source/hbase-VERSION/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift
Em seguida, você precisará obter o código do Thrift para seu idioma que contém todas as classes para conexão com o Thrift e seus protocolos. Este código pode ser encontrado em /path/to/thrift/thrift-0.9.0/lib/py/src/.
Aqui estão os comandos que executei para criar um projeto Python para usar o HBase Thrift:
$ mkdir HBaseThrift$ cd HBaseThrift/$ thrift -gen py ~/Downloads/hbase-0.94.2-cdh4.2.0/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift$ mv gen-py/* . $ rm -rf gen-py/$ mkdir thrift$ cp -rp ~/Downloads/thrift-0.9.0/lib/py/src/* ./thrift/
Eu gosto de manter uma cópia do arquivo Hbase.thrift no projeto para consultar. Tem muito “Javadoc” nas várias chamadas, objetos de dados e objetos de retorno.
$ cp ~/Downloads/hbase-0.94.2-cdh4.2.0/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift
Código de referência
Você verá que todos os seus scripts Python Thrift serão muito semelhantes. Vamos passar por cada parte.
de thrift.transport import TSocketfrom thrift.protocol import TBinaryProtocolfrom thrift.transport import TTransportfrom hbase import Hbase
Estes irão importar os módulos Thrift e HBase que você precisa.
# Conectar-se ao HBase Thrift servertransport =TTransport.TBufferedTransport(TSocket.TSocket(host, port))protocol =TBinaryProtocol.TBinaryProtocolAccelerated(transport)
Isso cria o protocolo de linha e transporte de soquete e permite que o cliente Thrift se conecte e converse com o servidor Thrift.
# Cria e abre o cliente connectionclient =Hbase.Client(protocol)transport.open()
Essas linhas criam o objeto Client que você usará para interagir com o HBase. A partir desse objeto cliente, você emitirá todos os seus Gets e Puts. Em seguida, abra o soquete para o servidor Thrift.
# Faça alguma coisa
Em seguida, você realmente trabalhará com o cliente HBase. Tudo é construído, inicializado e conectado. Primeiro, comece a usar o cliente.
transporte.fechar()
Finalmente, feche o transporte. Isso fecha o soquete e libera os recursos no servidor Thrift. Aqui está o código na íntegra para copiar e colar facilmente:
from thrift.transport import TSocketfrom thrift.protocol import TBinaryProtocolfrom thrift.transport import TTransportfrom hbase import Hbase# Conectar-se ao HBase Thrift servertransport =TTransport.TBufferedTransport(TSocket.TSocket(host, port))protocol =TBinaryProtocol.TBinaryProtocolAccelerated(transport) # Crie e abra o cliente connectionclient =Hbase.Client(protocol)transport.open()# Faça algotransport.close()
Na implementação Python do HBase Thrift, todos os valores são passados como strings. Isso inclui dados binários como um número inteiro. Todos os valores de coluna são mantidos no objeto TCell. Aqui está a definição no arquivo Hbase.thrift:
struct TCell{ 1:Bytes value, 2:i64 timestamp}
Observe a mudança para uma string quando o código Python é gerado:
thrift_spec =( Nenhum, # 0 (1, TType.STRING, 'value', None, None, ), # 1 (2, TType.I64, 'timestamp', None, None, ), # 2)
Escrevi um método auxiliar para facilitar o tratamento com números inteiros de 32 bits. Para alterar um inteiro para frente e para trás entre uma string, você usa esses dois métodos.
# Método para codificar inteiros com a string encodingdef encode(n) do Thrift: return struct.pack("i", n)# Método para decodificar inteiros com a string encodingdef decode(s) do Thrift: return struct.unpack('i' , s)[0]
Lembre-se dessa advertência ao trabalhar com dados binários no Thrift. Você precisará converter dados binários em strings e vice-versa.
Erro
Não é tão fácil quanto poderia ser entender os erros na interface do Thrift. Por exemplo, aqui está o erro que sai do Python quando uma tabela não é encontrada:
Traceback (última chamada mais recente): Arquivo "./get.py", linha 17, emlinhas =client.getRow(tablename, "shakespeare-comedies-000001") Arquivo "/mnt/hgfs/ jesse/repos/DevHivePigHBaseVM/training_materials/hbase/exercises/python_bleets_thrift/hbase/Hbase.py", linha 1038, em getRow return self.recv_getRow() Arquivo "/mnt/hgfs/jesse/repos/DevHivePigHBaseVM/training_materials/hbase/exercises /python_bleets_thrift/hbase/Hbase.py", linha 1062, em recv_getRow raise result.iohbase.ttypes.IOError:IOError(_message='doesnotexist')
Nem tudo está perdido porque você pode ver o arquivo de log do HBase Thrift. No CDH, esse arquivo está localizado em /var/log/hbase/hbase-hbase-thrift-localhost.localdomain.log. No exemplo da tabela ausente, você veria um erro no log do Thrift dizendo que a tabela não existe. É inconveniente, mas você pode depurar a partir daí.
Na próxima parte, abordarei a inserção e a obtenção de linhas.
Jesse Anderson é instrutor da Cloudera University.