Er zijn verschillende manieren om toegang te krijgen tot en te werken met Apache HBase. Met name de Java API biedt de meeste functionaliteit. Maar sommige mensen willen HBase gebruiken zonder Java.
Die mensen hebben twee hoofdopties:de ene is de Thrift-interface (de lichtere en dus snellere van de twee opties), en de andere is de REST-interface (ook bekend als Stargate). Een REST-interface gebruikt HTTP-werkwoorden om een actie uit te voeren. Door HTTP te gebruiken, biedt een REST-interface een veel breder scala aan talen en programma's die toegang hebben tot de interface. (Als je meer informatie wilt over de REST-interface, kun je mijn reeks how-to's erover raadplegen.)
In deze reeks how-to's leer je je weg te vinden in de Thrift-interface en verken je Python-codevoorbeelden om dat te doen. Dit eerste bericht gaat over HBase Thrift, werken met Thrift, en een aantal standaardcodes om verbinding te maken met Thrift. Het tweede bericht laat zien hoe je meerdere rijen tegelijk kunt invoegen en krijgen. In het derde bericht wordt uitgelegd hoe u scans gebruikt en enkele overwegingen bij het kiezen tussen REST en Thrift.
De volledige codevoorbeelden zijn te vinden op mijn GitHub-account.
HBase Thrift
Thrift is een softwareraamwerk waarmee u bindingen in meerdere talen kunt maken. Java is in het kader van HBase de enige eersteklas burger. Met de HBase Thrift-interface kunnen andere talen echter toegang krijgen tot HBase over Thrift door verbinding te maken met een Thrift-server die een interface heeft met de Java-client.
Om zowel Thrift als REST te laten werken, moet een andere HBase-daemon worden uitgevoerd om deze verzoeken af te handelen. Deze daemons kunnen worden geïnstalleerd met de pakketten hbase-thrift en hbase-rest. Het onderstaande diagram laat zien hoe Thrift en REST in het cluster zijn geplaatst.
Houd er rekening mee dat de Thrift- en REST-clienthosts meestal geen andere services uitvoeren (zoals DataNodes of RegionServers) om de overhead laag en het reactievermogen voor REST- of Thrift-interacties hoog te houden.
Zorg ervoor dat u deze daemons installeert en start op knooppunten die toegang hebben tot zowel het Hadoop-cluster als de toepassing die toegang tot HBase nodig heeft. De Thrift-interface heeft geen ingebouwde taakverdeling, dus alle taakverdeling moet worden gedaan met externe tools zoals een DNS-round-robin, een virtueel IP-adres of in code. Cloudera Manager maakt het ook heel eenvoudig om de HBase REST- en Thrift-services te installeren en te beheren. Je kunt het gratis downloaden en uitproberen in Cloudera Standard!
Het nadeel van Thrift is dat het moeilijker in te stellen is dan REST. U moet Thrift compileren en de taalspecifieke bindingen genereren. Deze bindingen zijn leuk omdat ze je code geven voor de taal waarin je werkt - het is niet nodig om XML of JSON te ontleden zoals in REST; in plaats daarvan geeft de Thrift-interface u directe toegang tot de rijgegevens. Een andere leuke eigenschap is dat het Thrift-protocol native binair transport heeft; u hoeft geen base64-gegevens te coderen en te decoderen.
Om de Thrift-interface te gaan gebruiken, moet je uitzoeken op welke poort deze draait. De standaardpoort voor CDH is poort 9090. Voor dit bericht zie je de gebruikte host- en poortvariabelen, dit zijn de waarden die we zullen gebruiken:
host = "localhost" port = "9090"
Je kunt de Thrift-interface instellen om Kerberos-inloggegevens te gebruiken voor een betere beveiliging.
Voor uw code moet u het IP-adres of de volledig gekwalificeerde domeinnaam van het knooppunt en de poort gebruiken waarop de Thrift-daemon wordt uitgevoerd. Ik raad ten zeerste aan om van deze URL een variabele te maken, omdat deze kan veranderen door netwerkwijzigingen.
Taalbindingen
Voordat u Thrift-bindingen kunt maken, moet u Thrift downloaden en compileren. Er zijn geen binaire pakketten voor Thrift die ik kon vinden, behalve op Windows. U moet de instructies van Thrift volgen voor de installatie op uw platform naar keuze.
Nadat Thrift is geïnstalleerd, moet u het Hbase.thrift-bestand vinden. Om de services en gegevenstypen in Thrift te definiëren, moet u een IDL-bestand maken. Gelukkig hebben de HBase-ontwikkelaars er al een voor ons gemaakt. Helaas wordt het bestand niet gedistribueerd als onderdeel van de CDH binaire pakketten. (We zullen dat oplossen in een toekomstige CDH-release.) U moet het bronpakket downloaden van de HBase-versie die u gebruikt. Zorg ervoor dat u de juiste versie van HBase gebruikt, aangezien deze IDL kan veranderen. In het gecomprimeerde bestand is het pad naar de IDL hbase-VERSION/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift.
Thrift ondersteunt het genereren van taalbindingen voor meer dan 14 talen, waaronder Java, C++, Python, PHP, Ruby en C#. Om de bindingen voor Python te genereren, zou je het volgende commando gebruiken:
thrift -gen py /path/to/hbase/source/hbase-VERSION/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift
Vervolgens moet je de Thrift-code voor je taal krijgen die alle klassen bevat voor verbinding met Thrift en zijn protocollen. Deze code is te vinden op /path/to/thrift/thrift-0.9.0/lib/py/src/.
Dit zijn de opdrachten die ik heb uitgevoerd om een Python-project te maken om HBase Thrift te gebruiken:
$ 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/
Ik bewaar graag een kopie van het Hbase.thrift-bestand in het project om naar terug te verwijzen. Het heeft veel "Javadoc" op de verschillende oproepen, gegevensobjecten en retourobjecten.
$ cp ~/Downloads/hbase-0.94.2-cdh4.2.0/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift
Ketelplaatcode
Je zult merken dat al je Python Thrift-scripts er erg op lijken. Laten we elk deel doornemen.
from thrift.transport import TSocket from thrift.protocol import TBinaryProtocol from thrift.transport import TTransport from hbase import Hbase
Deze zullen de Thrift- en HBase-modules importeren die u nodig hebt.
# Connect to HBase Thrift server transport = TTransport.TBufferedTransport(TSocket.TSocket(host, port)) protocol = TBinaryProtocol.TBinaryProtocolAccelerated(transport)
Dit creëert het sockettransport- en lijnprotocol en stelt de Thrift-client in staat om verbinding te maken en te praten met de Thrift-server.
# Create and open the client connection client = Hbase.Client(protocol) transport.open()
Deze regels maken het Client-object dat u gaat gebruiken voor interactie met HBase. Vanuit dit client-object geeft u al uw Gets en Puts uit. Open vervolgens de socket naar de Thrift-server.
# Do Something
Vervolgens werk je daadwerkelijk met de HBase-client. Alles is geconstrueerd, geïnitialiseerd en verbonden. Gebruik eerst de client.
transport.close()
Sluit tot slot het transport. Dit sluit de socket en maakt de bronnen op de Thrift-server vrij. Hier is de code in zijn geheel voor eenvoudig kopiëren en plakken:
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()
In de Python-implementatie van HBase Thrift worden alle waarden als tekenreeksen doorgegeven. Dit omvat binaire gegevens zoals een geheel getal. Alle kolomwaarden worden bewaard in het TCell-object. Hier is de definitie in het Hbase.thrift-bestand:
struct TCell{ 1:Bytes value, 2:i64 timestamp }
Let op de wijziging in een string wanneer de Python-code wordt gegenereerd:
thrift_spec = ( None, # 0 (1, TType.STRING, 'value', None, None, ), # 1 (2, TType.I64, 'timestamp', None, None, ), # 2 )
Ik heb een hulpmethode geschreven om het gemakkelijker te maken om met 32-bits gehele getallen om te gaan. Om een geheel getal heen en weer te wisselen tussen een string, gebruik je deze twee methoden.
# 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]
Houd dit voorbehoud in gedachten als u met binaire gegevens in Thrift werkt. U moet binaire gegevens converteren naar strings en vice versa.
Foutmelding
Het is niet zo eenvoudig als het zou kunnen zijn om fouten in de Thrift-interface te begrijpen. Dit is bijvoorbeeld de fout die uit Python komt wanneer een tabel niet wordt gevonden:
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')
Alles is echter niet verloren omdat u het HBase Thrift-logbestand kunt bekijken. Op CDH bevindt dit bestand zich op /var/log/hbase/hbase-hbase-thrift-localhost.localdomain.log. In het voorbeeld van de ontbrekende tabel ziet u een fout in het Thrift-logboek waarin staat dat de tabel niet bestaat. Het is onhandig, maar je kunt vanaf daar debuggen.
In de volgende aflevering behandel ik het invoegen en ophalen van rijen.
Jesse Anderson is een instructeur voor Cloudera University.