sql >> Base de Datos >  >> NoSQL >> HBase

Procedimiento:utilizar la interfaz Thrift de HBase, parte 1

Hay varias formas de acceder e interactuar con Apache HBase. En particular, la API de Java proporciona la mayor funcionalidad. Pero algunas personas quieren usar HBase sin Java.

Esas personas tienen dos opciones principales:una es la interfaz Thrift (la más liviana y, por lo tanto, más rápida de las dos opciones) y la otra es la interfaz REST (también conocida como Stargate). Una interfaz REST usa verbos HTTP para realizar una acción. Mediante el uso de HTTP, una interfaz REST ofrece una gama mucho más amplia de lenguajes y programas que pueden acceder a la interfaz. (Si desea obtener más información sobre la interfaz REST, puede consultar mi serie de procedimientos al respecto).

En esta serie de procedimientos, aprenderá a usar la interfaz de Thrift y explorará muestras de código de Python para hacerlo. Esta primera publicación cubrirá HBase Thrift, trabajando con Thrift y algunos códigos repetitivos para conectarse a Thrift. La segunda publicación mostrará cómo insertar y obtener varias filas a la vez. La tercera publicación explicará cómo usar los escaneos y algunas consideraciones al elegir entre REST y Thrift.

Los ejemplos de código completos se pueden encontrar en mi cuenta de GitHub.

Ahorro HBase

Thrift es un marco de software que le permite crear enlaces entre idiomas. En el contexto de HBase, Java es el único ciudadano de primera clase. Sin embargo, la interfaz HBase Thrift permite que otros lenguajes accedan a HBase sobre Thrift al conectarse a un servidor Thrift que interactúa con el cliente Java.

Para que tanto Thrift como REST funcionen, se debe ejecutar otro demonio HBase para manejar estas solicitudes. Estos demonios se pueden instalar con los paquetes hbase-thrift y hbase-rest. El siguiente diagrama muestra cómo se colocan Thrift y REST en el clúster.

Tenga en cuenta que los hosts de clientes Thrift y REST generalmente no ejecutan ningún otro servicio (como DataNodes o RegionServers) para mantener la sobrecarga baja y la capacidad de respuesta alta para las interacciones REST o Thrift.

Asegúrese de instalar e iniciar estos demonios en nodos que tengan acceso tanto al clúster de Hadoop como a la aplicación que necesita acceso a HBase. La interfaz de Thrift no tiene ningún equilibrio de carga incorporado, por lo que todo el equilibrio de carga deberá realizarse con herramientas externas, como DNS por turnos, una dirección IP virtual o en código. Cloudera Manager también hace que sea realmente fácil instalar y administrar los servicios HBase REST y Thrift. ¡Puedes descargarlo y probarlo gratis en Cloudera Standard!

La desventaja de Thrift es que es más difícil de configurar que REST. Deberá compilar Thrift y generar los enlaces específicos del idioma. Estos enlaces son buenos porque le brindan código para el idioma en el que está trabajando; no es necesario analizar XML o JSON como en REST; más bien, la interfaz Thrift le brinda acceso directo a los datos de la fila. Otra buena característica es que el protocolo Thrift tiene transporte binario nativo; no necesitará codificar y decodificar datos en base64.

Para comenzar a usar la interfaz Thrift, debe averiguar en qué puerto se está ejecutando. El puerto predeterminado para CDH es el puerto 9090. Para esta publicación, verá las variables de host y puerto utilizadas, estos son los valores que usaremos:

host = "localhost"
port = "9090"

Puede configurar la interfaz de Thrift para usar las credenciales de Kerberos para mejorar la seguridad.

Para su código, deberá usar la dirección IP o el nombre de dominio completo del nodo y el puerto que ejecuta el demonio Thrift. Recomiendo encarecidamente hacer de esta URL una variable, ya que podría cambiar con los cambios en la red.

Enlaces de idioma

Antes de poder crear enlaces de Thrift, debe descargar y compilar Thrift. No hay paquetes binarios para Thrift que pueda encontrar, excepto en Windows. Deberá seguir las instrucciones de Thrift para la instalación en la plataforma que elija.

Una vez que Thrift está instalado, debe encontrar el archivo Hbase.thrift. Para definir los servicios y tipos de datos en Thrift, debe crear un archivo IDL. Afortunadamente, los desarrolladores de HBase ya crearon uno para nosotros. Desafortunadamente, el archivo no se distribuye como parte de los paquetes binarios de CDH. (Lo corregiremos en una versión futura de CDH). Deberá descargar el paquete fuente de la versión de HBase que está utilizando. Asegúrese de utilizar la versión correcta de HBase, ya que esta IDL podría cambiar. En el archivo comprimido, la ruta al IDL es hbase-VERSION/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift.

Thrift admite la generación de enlaces de idiomas para más de 14 idiomas, incluidos Java, C++, Python, PHP, Ruby y C#. Para generar los enlaces para Python, usaría el siguiente comando:

thrift -gen py /path/to/hbase/source/hbase-VERSION/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift

A continuación, deberá obtener el código Thrift para su idioma que contiene todas las clases para conectarse a Thrift y sus protocolos. Este código se puede encontrar en /path/to/thrift/thrift-0.9.0/lib/py/src/.

Estos son los comandos que ejecuté para crear un proyecto de Python para usar 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/

Me gusta guardar una copia del archivo Hbase.thrift en el proyecto para consultarlo. Tiene mucho "Javadoc" en las diversas llamadas, objetos de datos y objetos de retorno.

$ cp ~/Downloads/hbase-0.94.2-cdh4.2.0/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift

Código repetitivo

Descubrirá que todos sus scripts de Python Thrift se verán muy similares. Repasemos cada parte.

from thrift.transport import TSocket
from thrift.protocol import TBinaryProtocol
from thrift.transport import TTransport
from hbase import Hbase

Estos importarán los módulos Thrift y HBase que necesita.

# Connect to HBase Thrift server
transport = TTransport.TBufferedTransport(TSocket.TSocket(host, port))
protocol = TBinaryProtocol.TBinaryProtocolAccelerated(transport)

Esto crea el protocolo de línea y transporte de socket y permite que el cliente Thrift se conecte y hable con el servidor Thrift.

# Create and open the client connection
client = Hbase.Client(protocol)
transport.open()

Estas líneas crean el objeto Cliente que utilizará para interactuar con HBase. Desde este objeto de cliente, emitirá todos sus Gets y Puts. A continuación, abra el zócalo del servidor Thrift.

# Do Something

A continuación, trabajará con el cliente HBase. Todo está construido, inicializado y conectado. Primero, comience a usar el cliente.

transport.close()

Finalmente, cierre el transporte. Esto cierra el socket y libera los recursos en el servidor Thrift. Aquí está el código completo para copiarlo y pegarlo fácilmente:

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()

En la implementación de Python de HBase Thrift, todos los valores se transmiten como cadenas. Esto incluye datos binarios como un número entero. Todos los valores de columna se mantienen en el objeto TCell. Aquí está la definición en el archivo Hbase.thrift:

struct TCell{
  1:Bytes value,
  2:i64 timestamp
}

Observe el cambio en una cadena cuando se genera el código de Python:

thrift_spec = (
    None, # 0
    (1, TType.STRING, 'value', None, None, ), # 1
    (2, TType.I64, 'timestamp', None, None, ), # 2
)

Escribí un método auxiliar para facilitar el manejo de números enteros de 32 bits. Para cambiar un número entero de una cadena a otra, utilice estos dos métodos.

# 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]

Tenga en cuenta esta advertencia cuando trabaje con datos binarios en Thrift. Deberá convertir datos binarios en cadenas y viceversa.

Error

No es tan fácil como podría ser comprender los errores en la interfaz de Thrift. Por ejemplo, aquí está el error que sale de Python cuando no se encuentra una tabla:

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')

Sin embargo, no todo está perdido porque puede consultar el archivo de registro de HBase Thrift. En CDH, este archivo se encuentra en /var/log/hbase/hbase-hbase-thrift-localhost.localdomain.log. En el ejemplo de la tabla que falta, vería un error en el registro de Thrift que indica que la tabla no existe. Es un inconveniente, pero puede depurar desde allí.

En la próxima entrega, cubriré la inserción y obtención de filas.

Jesse Anderson es profesor de la Universidad de Cloudera.