Istnieją różne sposoby uzyskiwania dostępu i interakcji z Apache HBase. Przede wszystkim Java API zapewnia największą funkcjonalność. Ale niektórzy ludzie chcą używać HBase bez Javy.
Ci ludzie mają dwie główne opcje:jedną jest interfejs Thrift (bardziej lekki, a tym samym szybszy z dwóch opcji), a drugą jest interfejs REST (znany również jako Stargate). Interfejs REST używa czasowników HTTP do wykonania akcji. Korzystając z protokołu HTTP, interfejs REST oferuje znacznie szerszą gamę języków i programów, które mogą uzyskać dostęp do interfejsu. (Jeśli chcesz uzyskać więcej informacji o interfejsie REST, możesz przejść do mojej serii poradników na ten temat.)
W tej serii poradników nauczysz się, jak poruszać się po interfejsie Thrift i zapoznasz się z przykładami kodu Pythona, aby to zrobić. W tym pierwszym poście omówimy HBase Thrift, współpracujący z Thrift, oraz kod wzorcowy do łączenia się z Thrift. Drugi post pokaże, jak wstawiać i pobierać wiele wierszy naraz. W trzecim poście wyjaśnimy, jak korzystać ze skanów i jakie kwestie należy wziąć pod uwagę przy wyborze między REST a Thrift.
Pełne próbki kodu można znaleźć na moim koncie GitHub.
HBase Thrift
Thrift to platforma programowa, która umożliwia tworzenie powiązań między językami. W kontekście HBase Java jest jedynym obywatelem pierwszej klasy. Jednak interfejs HBase Thrift umożliwia innym językom dostęp do HBase przez Thrift, łącząc się z serwerem Thrift, który łączy się z klientem Java.
Aby zarówno Thrift, jak i REST działały, inny demon HBase musi być uruchomiony do obsługi tych żądań. Te demony można zainstalować z pakietami hbase-thrift i hbase-rest. Poniższy diagram pokazuje, w jaki sposób Thrift i REST są umieszczone w klastrze.
Pamiętaj, że hosty klientów Thrift i REST zwykle nie uruchamiają żadnych innych usług (takich jak DataNodes lub RegionServers), aby utrzymać niskie obciążenie i wysoką responsywność w przypadku interakcji REST lub Thrift.
Upewnij się, że instalujesz i uruchamiasz te demony w węzłach, które mają dostęp zarówno do klastra Hadoop, jak i aplikacji wymagającej dostępu do HBase. Interfejs Thrift nie ma wbudowanego równoważenia obciążenia, więc całe równoważenie obciążenia będzie musiało być wykonane za pomocą zewnętrznych narzędzi, takich jak DNS round-robin, wirtualny adres IP lub w kodzie. Cloudera Manager ułatwia również instalację i zarządzanie usługami HBase REST i Thrift. Możesz pobrać i wypróbować za darmo w Cloudera Standard!
Minusem Thrift jest to, że jest trudniejszy do skonfigurowania niż REST. Będziesz musiał skompilować Thrift i wygenerować powiązania specyficzne dla języka. Te powiązania są fajne, ponieważ dają kod dla języka, w którym pracujesz — nie ma potrzeby parsowania XML lub JSON, jak w REST; raczej interfejs Thrift zapewnia bezpośredni dostęp do danych wiersza. Kolejną fajną cechą jest to, że protokół Thrift ma natywny transport binarny; nie będziesz musiał kodować i dekodować danych w base64.
Aby zacząć korzystać z interfejsu Thrift, musisz dowiedzieć się, na którym porcie jest uruchomiony. Domyślnym portem dla CDH jest port 9090. W tym poście zobaczysz użyte zmienne hosta i portu. Oto wartości, których będziemy używać:
host = "localhost" port = "9090"
Możesz skonfigurować interfejs Thrift, aby używał danych logowania Kerberos w celu zwiększenia bezpieczeństwa.
W przypadku kodu musisz użyć adresu IP lub w pełni kwalifikowanej nazwy domeny węzła i portu, na którym działa demon Thrift. Gorąco polecam, aby ten adres URL był zmienną, ponieważ może się zmieniać wraz ze zmianami sieci.
Powiązania językowe
Zanim będziesz mógł tworzyć powiązania Thrift, musisz pobrać i skompilować Thrift. Nie ma pakietów binarnych dla Thrift, które mógłbym znaleźć, z wyjątkiem systemu Windows. Będziesz musiał postępować zgodnie z instrukcjami Thrift, aby zainstalować na wybranej platformie.
Po zainstalowaniu Thrift musisz znaleźć plik Hbase.thrift. Aby zdefiniować usługi i typy danych w Thrift, musisz utworzyć plik IDL. Na szczęście programiści HBase już go dla nas stworzyli. Niestety plik nie jest rozpowszechniany jako część pakietów binarnych CDH. (Będziemy to naprawić w przyszłym wydaniu CDH.) Będziesz musiał pobrać pakiet źródłowy używanej wersji HBase. Upewnij się, że używasz poprawnej wersji HBase, ponieważ ten IDL może się zmienić. W skompresowanym pliku ścieżka do IDL to hbase-VERSION/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift.
Thrift obsługuje generowanie powiązań językowych dla ponad 14 języków, w tym Java, C++, Python, PHP, Ruby i C#. Aby wygenerować wiązania dla Pythona, użyjesz następującego polecenia:
thrift -gen py /path/to/hbase/source/hbase-VERSION/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift
Następnie będziesz musiał uzyskać kod Thrift dla swojego języka, który zawiera wszystkie klasy do połączenia z Thrift i jego protokołami. Ten kod można znaleźć w /ścieżka/do/thrift/thrift-0.9.0/lib/py/src/.
Oto polecenia, które uruchomiłem, aby utworzyć projekt w Pythonie do korzystania z 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/
Lubię przechowywać kopię pliku Hbase.thrift w projekcie, aby móc się do niego odwołać. Ma dużo „Javadoc” w różnych wywołaniach, obiektach danych i obiektach zwracanych.
$ cp ~/Downloads/hbase-0.94.2-cdh4.2.0/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift
Kod kotła
Przekonasz się, że wszystkie twoje skrypty Python Thrift będą wyglądać bardzo podobnie. Przejdźmy przez każdą część.
from thrift.transport import TSocket from thrift.protocol import TBinaryProtocol from thrift.transport import TTransport from hbase import Hbase
Spowodują one zaimportowanie potrzebnych modułów Thrift i HBase.
# Connect to HBase Thrift server transport = TTransport.TBufferedTransport(TSocket.TSocket(host, port)) protocol = TBinaryProtocol.TBinaryProtocolAccelerated(transport)
Tworzy to transport gniazda i protokół linii oraz umożliwia klientowi Thrift łączenie się i komunikowanie z serwerem Thrift.
# Create and open the client connection client = Hbase.Client(protocol) transport.open()
Te linie tworzą obiekt klienta, którego będziesz używać do interakcji z HBase. Z tego obiektu klienta wydasz wszystkie swoje Gets and Puts. Następnie otwórz gniazdo do serwera Thrift.
# Do Something
Następnie będziesz pracować z klientem HBase. Wszystko jest konstruowane, inicjowane i połączone. Najpierw zacznij korzystać z klienta.
transport.close()
Na koniec zamknij transport. To zamyka gniazdo i zwalnia zasoby na serwerze Thrift. Oto cały kod do łatwego kopiowania i wklejania:
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()
W implementacji Pythona HBase Thrift wszystkie wartości są przekazywane jako ciągi. Obejmuje to dane binarne, takie jak liczba całkowita. Wszystkie wartości kolumn są przechowywane w obiekcie TCell. Oto definicja w pliku Hbase.thrift:
struct TCell{ 1:Bytes value, 2:i64 timestamp }
Zwróć uwagę na zmianę w łańcuchu podczas generowania kodu Pythona:
thrift_spec = ( None, # 0 (1, TType.STRING, 'value', None, None, ), # 1 (2, TType.I64, 'timestamp', None, None, ), # 2 )
Napisałem metodę pomocniczą, aby ułatwić radzenie sobie z 32-bitowymi liczbami całkowitymi. Aby zmienić liczbę całkowitą tam iz powrotem między łańcuchem, użyj tych dwóch metod.
# 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]
Pamiętaj o tym zastrzeżeniu podczas pracy z danymi binarnymi w Thrift. Będziesz musiał przekonwertować dane binarne na ciągi i odwrotnie.
Błąd
Zrozumienie błędów w interfejsie Thrift nie jest tak łatwe, jak mogłoby być. Na przykład, oto błąd, który pojawia się w Pythonie, gdy tabela nie zostanie znaleziona:
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')
Nie wszystko jest jednak stracone, ponieważ możesz spojrzeć na plik dziennika HBase Thrift. W CDH ten plik znajduje się w /var/log/hbase/hbase-hbase-thrift-localhost.localdomain.log. W przykładzie brakującej tabeli zobaczysz błąd w dzienniku Thrift, mówiący, że tabela nie istnieje. Jest to niewygodne, ale możesz stamtąd debugować.
W następnej części omówię wstawianie i pobieranie wierszy.
Jesse Anderson jest wykładowcą na Uniwersytecie Cloudera.