Existem várias maneiras de acessar e interagir com o Apache HBase. A API Java fornece mais funcionalidades, mas muitas pessoas querem usar o HBase sem Java.
Existem duas abordagens principais para fazer isso: Uma é a interface Thrift, que é a mais rápida e leve das duas opções. A outra maneira de acessar o HBase é usando a interface REST, que usa verbos HTTP para executar uma ação, oferecendo aos desenvolvedores uma ampla variedade de linguagens e programas a serem usados.
Esta série de instruções discutirá a interface REST e fornecerá exemplos de código Python para acessá-la. A primeira postagem abordará o HBase REST, algumas advertências do Python e a administração de tabelas. A segunda postagem explicará como inserir várias linhas de uma vez usando XML e JSON. O terceiro post mostrará como obter várias linhas usando XML e JSON. Os exemplos de código completos podem ser encontrados na minha conta do GitHub.
Noções básicas de REST do HBase
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 nos pacotes hbase-thrift e hbase-rest. O diagrama abaixo ilustra onde Thrift e REST são colocados no cluster. Observe que os clientes Thrift e REST geralmente não executam outros serviços de serviços, como DataNode ou RegionServers, para manter a carga baixa e a capacidade de resposta alta para interações REST.
Certifique-se de instalar e iniciar esses daemons em nós que tenham acesso ao cluster Hadoop e ao servidor de aplicativos da web. A interface REST não possui balanceamento de carga integrado; que precisará ser feito com hardware ou em código. O Cloudera Manager facilita muito a instalação e o gerenciamento dos serviços HBase REST e Thrift. (Você pode fazer o download e experimentá-lo gratuitamente!) A desvantagem do REST é que ele é muito mais pesado do que Thrift ou Java.
Uma interface REST pode usar vários formatos de dados:XML, JSON e protobuf. Especificando o Accept
e Content-Type
cabeçalhos, você pode escolher o formato que deseja transmitir ou receber de volta.
Para começar a usar a interface REST, você precisa descobrir em qual porta ela está sendo executada. A porta padrão para CDH é a porta 8070. Para esta postagem, você verá o baseurl
variável usada, e aqui está o valor que estarei usando::
baseurl = "http://localhost:8070"
A interface REST pode ser configurada para usar uma credencial Kerberos para aumentar a segurança.
Para seu código, você precisará usar o endereço IP ou o DNS do nome de domínio totalmente qualificado do nó que executa o daemon REST. Além disso, confirme se a porta está correta. É altamente recomendável tornar esse URL uma variável, pois ele pode mudar com as alterações da rede.
Soluções alternativas de bugs Python e HBase
Há dois bugs e soluções alternativas que precisam ser resolvidos. O primeiro bug é que os módulos internos do Python não suportam todos os verbos HTTP. O segundo é um bug HBase REST ao trabalhar com JSON.
Os módulos internos do Python para interação REST não suportam facilmente todos os verbos HTTP necessários para o HBase REST. Você precisará instalar o módulo de solicitações do Python. O módulo de solicitações também limpa o código e facilita muito todas as interações.
A interface REST do HBase apresenta um bug ao adicionar dados via JSON:é necessário que os campos mantenham sua ordem exata. O
dict
do Python embutido type não oferece suporte a esse recurso, portanto, para manter o pedido, precisaremos usar o OrderedDict
aula. (Aqueles com Python 2.6 e anteriores precisarão instalar o módulo orderdict.) Também abordarei o bug e a solução alternativa mais adiante no post. Também era difícil usar inteiros para codificar e decodificar em base64, então escrevi um código para fazer isso:
# Method for encoding ints with base64 encoding def encode(n): data = struct.pack("i", n) s = base64.b64encode(data) return s # Method for decoding ints with base64 encoding def decode(s): data = base64.b64decode(s) n = struct.unpack("i", data) return n[0]
Para tornar as coisas ainda mais fáceis, escrevi um método para confirmar que as respostas HTTP voltam nos anos 200, o que indica que a operação funcionou. O código de exemplo usa esse método para verificar o sucesso de uma chamada antes de prosseguir. Aqui está o método:
# Checks the request object to see if the call was successful def issuccessful(request): if 200
Trabalhando com tabelas
Usando a interface REST, você pode criar ou excluir tabelas. Vamos dar uma olhada no código para criar uma tabela.
content = '' content += '' content += ' ' content += '' request = requests.post(baseurl + "/" + tablename + "/schema", data=content, headers={"Content-Type" : "text/xml", "Accept" : "text/xml"})
Neste trecho, criamos um pequeno documento XML que define o esquema da tabela na variável content. Precisamos fornecer o nome da tabela e o nome da família de colunas. Se houver várias famílias de colunas, você cria mais
ColumnSchema
nós. Em seguida, usamos o módulo de solicitações para
POST
o XML para a URL que criamos. Essa URL precisa incluir o nome da nova tabela. Além disso, observe que estamos definindo os cabeçalhos para este POST
ligar. Estamos mostrando que estamos enviando em XML com o Content-Type
definido como "text/xml" e que queremos XML de volta com o Accept
definido como "texto/xml". Usando o
request.status_code
, você pode verificar se a criação da tabela foi bem-sucedida. A interface REST usa os mesmos códigos de erro HTTP para detectar se uma chamada foi bem-sucedida ou falhou. Um código de status nos anos 200 significa que as coisas funcionaram corretamente. Podemos verificar facilmente se existe uma tabela usando o seguinte código:
request = requests.get(baseurl + "/" + tablename + "/schema")
As chamadas usam o
GET
verbo para informar à interface REST que queremos obter as informações do esquema sobre a tabela na URL. Mais uma vez, podemos usar o código de status para ver se a tabela existe. Um código de status na casa dos 200 significa que existe e qualquer outro número significa que não. Usando o
curl
comando, podemos verificar o sucesso de uma operação REST sem escrever código. O comando a seguir retornará um 200 mostrando o sucesso da chamada porque o messagestable
tabela existe no HBase. Aqui está a chamada e sua saída:[user@localhost]$ curl -I -H "Accept: text/xml" http://localhost:8070/messagestable/schema HTTP/1.1 200 OK Content-Length: 0 Cache-Control: no-cache Content-Type: text/xml
Esta chamada REST apresentará um erro porque o
tablenotthere
tabela não existe no HBase. Aqui está a chamada e sua saída:[user@localhost]$ curl -I -H "Accept: text/xml" http://localhost:8070/tablenotthere/schema HTTP/1.1 500 org.apache.hadoop.hbase.TableNotFoundException: tablenotthere Content-Type: text/html; charset=iso-8859-1 Cache-Control: must-revalidate,no-cache,no-store Content-Length: 10767
Podemos excluir uma tabela usando o seguinte código:
request = requests.delete(baseurl + "/" + tablename + "/schema")
Esta chamada usa o
DELETE
verbo para dizer à interface REST que queremos excluir a tabela. A exclusão de uma tabela por meio da interface REST não exige que você a desative primeiro. Como de costume, podemos confirmar o sucesso observando o código de status. Na próxima postagem desta série, abordaremos a inserção de linhas.
Jesse Anderson é instrutor da Cloudera University.
Se você estiver interessado no HBase, certifique-se de se registrar para HBaseCon 2013 (13 de junho, São Francisco) – O evento da comunidade para colaboradores, desenvolvedores, administradores e usuários do HBase. As inscrições antecipadas estão abertas até 23 de abril.