Esistono vari modi per accedere e interagire con Apache HBase. In particolare, l'API Java fornisce la maggior parte delle funzionalità. Ma alcune persone vogliono usare HBase senza Java.
Queste persone hanno due opzioni principali:una è l'interfaccia Thrift (la più leggera e quindi più veloce delle due opzioni) e l'altra è l'interfaccia REST (aka Stargate). Un'interfaccia REST utilizza i verbi HTTP per eseguire un'azione. Utilizzando HTTP, un'interfaccia REST offre una gamma molto più ampia di linguaggi e programmi che possono accedere all'interfaccia. (Se desideri maggiori informazioni sull'interfaccia REST, puoi consultare la mia serie di istruzioni al riguardo.)
In questa serie di istruzioni imparerai come aggirare l'interfaccia Thrift ed esplorerai esempi di codice Python per farlo. Questo primo post riguarderà HBase Thrift, il lavoro con Thrift e alcuni codici standard per la connessione a Thrift. Il secondo post mostrerà come inserire e ottenere più righe alla volta. Il terzo post spiegherà come utilizzare le scansioni e alcune considerazioni sulla scelta tra REST e Thrift.
Gli esempi di codice completo possono essere trovati sul mio account GitHub.
Parsimonia di HBase
Thrift è un framework software che consente di creare collegamenti multilingua. Nel contesto di HBase, Java è l'unico cittadino di prima classe. Tuttavia, l'interfaccia HBase Thrift consente ad altre lingue di accedere a HBase su Thrift collegandosi a un server Thrift che si interfaccia con il client Java.
Affinché sia Thrift che REST funzionino, è necessario che un altro demone HBase sia in esecuzione per gestire queste richieste. Questi demoni possono essere installati con i pacchetti hbase-thrift e hbase-rest. Il diagramma seguente mostra come vengono posizionati Thrift e REST nel cluster.
Tieni presente che gli host dei client Thrift e REST di solito non eseguono altri servizi (come DataNodes o RegionServers) per mantenere il sovraccarico basso e la reattività elevata per le interazioni REST o Thrift.
Assicurati di installare e avviare questi daemon sui nodi che hanno accesso sia al cluster Hadoop che all'applicazione che necessita dell'accesso a HBase. L'interfaccia Thrift non ha alcun bilanciamento del carico integrato, quindi tutto il bilanciamento del carico dovrà essere eseguito con strumenti esterni come un round-robin DNS, un indirizzo IP virtuale o nel codice. Cloudera Manager semplifica anche l'installazione e la gestione dei servizi HBase REST e Thrift. Puoi scaricarlo e provarlo gratuitamente in Cloudera Standard!
Lo svantaggio di Thrift è che è più difficile da configurare rispetto a REST. Sarà necessario compilare Thrift e generare i collegamenti specifici della lingua. Questi collegamenti sono utili perché ti danno il codice per la lingua in cui stai lavorando:non è necessario analizzare XML o JSON come in REST; piuttosto, l'interfaccia Thrift ti dà accesso diretto ai dati della riga. Un'altra caratteristica interessante è che il protocollo Thrift ha il trasporto binario nativo; non sarà necessario codificare e decodificare i dati in base64.
Per iniziare a utilizzare l'interfaccia Thrift, devi capire su quale porta è in esecuzione. La porta predefinita per CDH è la porta 9090. Per questo post vedrai le variabili host e port utilizzate, ecco i valori che utilizzeremo:
host = "localhost" port = "9090"
Puoi configurare l'interfaccia Thrift per utilizzare le credenziali Kerberos per una maggiore sicurezza.
Per il tuo codice, dovrai utilizzare l'indirizzo IP o il nome di dominio completo del nodo e la porta che esegue il demone Thrift. Consiglio vivamente di rendere questo URL una variabile in quanto potrebbe cambiare con le modifiche alla rete.
Legature linguistiche
Prima di poter creare associazioni Thrift, devi scaricare e compilare Thrift. Non ci sono pacchetti binari per Thrift che potrei trovare, tranne su Windows. Dovrai seguire le istruzioni di Thrift per l'installazione sulla tua piattaforma preferita.
Una volta installato Thrift, è necessario trovare il file Hbase.thrift. Per definire i servizi e i tipi di dati in Thrift, devi creare un file IDL. Fortunatamente, gli sviluppatori HBase ne hanno già creato uno per noi. Sfortunatamente, il file non è distribuito come parte dei pacchetti binari CDH. (Lo risolveremo in una futura versione CDH.) Dovrai scaricare il pacchetto sorgente della versione HBase che stai utilizzando. Assicurati di utilizzare la versione corretta di HBase poiché questo IDL potrebbe cambiare. Nel file compresso, il percorso dell'IDL è hbase-VERSION/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift.
Thrift supporta la generazione di binding di lingua per più di 14 linguaggi, inclusi Java, C++, Python, PHP, Ruby e C#. Per generare i collegamenti per Python, dovresti utilizzare il seguente comando:
thrift -gen py /path/to/hbase/source/hbase-VERSION/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift
Successivamente, dovrai ottenere il codice Thrift per la tua lingua che contiene tutte le classi per la connessione a Thrift e ai suoi protocolli. Questo codice può essere trovato in /path/to/thrift/thrift-0.9.0/lib/py/src/.
Ecco i comandi che ho eseguito per creare un progetto Python per utilizzare 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/
Mi piace conservare una copia del file Hbase.thrift nel progetto a cui fare riferimento. Ha molto "Javadoc" sulle varie chiamate, oggetti dati e oggetti restituiti.
$ cp ~/Downloads/hbase-0.94.2-cdh4.2.0/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift
Codice caldaia
Scoprirai che tutti i tuoi script Python Thrift saranno molto simili. Esaminiamo ogni parte.
from thrift.transport import TSocket from thrift.protocol import TBinaryProtocol from thrift.transport import TTransport from hbase import Hbase
Questi importeranno i moduli Thrift e HBase di cui hai bisogno.
# Connect to HBase Thrift server transport = TTransport.TBufferedTransport(TSocket.TSocket(host, port)) protocol = TBinaryProtocol.TBinaryProtocolAccelerated(transport)
Questo crea il trasporto socket e il protocollo di linea e consente al client Thrift di connettersi e parlare con il server Thrift.
# Create and open the client connection client = Hbase.Client(protocol) transport.open()
Queste righe creano l'oggetto Client che utilizzerai per interagire con HBase. Da questo oggetto client, emetterai tutti i tuoi Get e Put. Quindi, apri il socket sul server Thrift.
# Do Something
Successivamente lavorerai effettivamente con il client HBase. Tutto è costruito, inizializzato e connesso. Innanzitutto, inizia a utilizzare il client.
transport.close()
Infine, chiudere il trasporto. Questo chiude il socket e libera le risorse sul server Thrift. Ecco il codice nella sua interezza per copiare e incollare facilmente:
from thrift.transport import TSocket from thrift.protocol import TBinaryProtocol from thrift.transport import TTransport from hbase import Hbase # Connect to HBase Thrift server transport = TTransport.TBufferedTransport(TSocket.TSocket(host, port)) protocol = TBinaryProtocol.TBinaryProtocolAccelerated(transport) # Create and open the client connection client = Hbase.Client(protocol) transport.open() # Do Something transport.close()
Nell'implementazione Python di HBase Thrift, tutti i valori vengono passati come stringhe. Ciò include dati binari come un numero intero. Tutti i valori delle colonne vengono mantenuti nell'oggetto TCell. Ecco la definizione nel file Hbase.thrift:
struct TCell{ 1:Bytes value, 2:i64 timestamp }
Nota la modifica a una stringa quando viene generato il codice Python:
thrift_spec = ( None, # 0 (1, TType.STRING, 'value', None, None, ), # 1 (2, TType.I64, 'timestamp', None, None, ), # 2 )
Ho scritto un metodo di supporto per semplificare la gestione degli interi a 32 bit. Per cambiare un numero intero avanti e indietro tra una stringa, usi questi due metodi.
# Method for encoding ints with Thrift's string encoding def encode(n): return struct.pack("i", n) # Method for decoding ints with Thrift's string encoding def decode(s): return struct.unpack('i', s)[0]
Tieni presente questo avvertimento mentre lavori con i dati binari in Thrift. Dovrai convertire i dati binari in stringhe e viceversa.
Errore
Non è così facile come potrebbe essere capire gli errori nell'interfaccia di Thrift. Ad esempio, ecco l'errore che esce da Python quando non viene trovata una tabella:
Traceback (most recent call last): File "./get.py", line 17, in <module> rows = client.getRow(tablename, "shakespeare-comedies-000001") File "/mnt/hgfs/jesse/repos/DevHivePigHBaseVM/training_materials/hbase/exercises/python_bleets_thrift/hbase/Hbase.py", line 1038, in getRow return self.recv_getRow() File "/mnt/hgfs/jesse/repos/DevHivePigHBaseVM/training_materials/hbase/exercises/python_bleets_thrift/hbase/Hbase.py", line 1062, in recv_getRow raise result.io hbase.ttypes.IOError: IOError(_message='doesnotexist')
Tuttavia, non tutto è perso perché puoi guardare il file di registro HBase Thrift. Su CDH, questo file si trova in /var/log/hbase/hbase-hbase-thrift-localhost.localdomain.log. Nell'esempio della tabella mancante, vedrai un errore nel registro dell'usato che dice che la tabella non esiste. È scomodo, ma puoi eseguire il debug da lì.
Nella prossima puntata tratterò l'inserimento e il recupero delle righe.
Jesse Anderson è un istruttore per la Cloudera University.