Un poco de autopromoción: trabajo en WI (http://wi.co/). Estamos cambiando la forma de trabajar de la gente fuera de Silicon Valley. Si te interesa, echa un vistazo a nuestra página de empleo (http://wi.co/careers) o envíame un correo electrónico a [email protected]
Acerca de Thrift: Si no estás familiarizado con RPC o Thrift, quizá te interese echar un vistazo a https://thrift.apache.org/
Bueno, un problema del que he oído hablar es: «Oye, vamos a publicar nuestras API de Thrift para que las utilicen terceros, y necesitamos que sean fáciles de usar». Ahora bien, tienes dos opciones:
- Da a conocer los puntos de conexión de Thrift, forma a los usuarios de tu API en el uso de Thrift y ayúdales a solucionar cualquier problema.
- Mantienes una biblioteca que actúa como envoltura de los distintos servicios de Thrift para cada lenguaje o plataforma que quieras admitir.
- Crea una forma de convertir manualmente entre JSON legible para el usuario a Thrift y viceversa, y mantenerla para cada estructura, servicio y función.
Si estas opciones no te parecen atractivas, tienes razón: pueden suponer mucho trabajo. Pero, ¿hay alguna otra forma de hacerlo?
En el artículo que aparece a continuación voy a utilizar el siguiente archivo Thrift sencillo:
Ahora bien, Thrift sí admite un JSONProtocol que transmite datos en formato JSON entre el cliente y el servidor (esto es lo que utilizamos para nuestra interfaz web). Sin embargo, basta con echar un vistazo a los datos que se envían para darse cuenta de que no va a ser posible compartirlos con terceros:
Y esto es para una llamada muy sencilla : login(correo electrónico, contraseña).
El JSON de Thrift utiliza toda una serie de términos técnicos para analizar la llamada exacta, como los tipos de cada argumento o campo, la longitud de las matrices o conjuntos, el número de clave de cada campo en una estructura, etc.
Así que se nos ocurrió una forma de convertir JSON legible para el ser humano a Thrift sin:
- Añadir un montón de jerga
- Se está realizando algún tipo de mantenimiento. Cualquier cambio en las definiciones de Thrift debería poder utilizarse automáticamente.
Un ejemplo de la misma llamada utilizando el nuevo método:
¡Se lee mucho mejor!
El formato es sencillo. Los valores de la clave «method» deben coincidir exactamente con el nombre del método en la definición de Thrift. El objeto «arguments» es la lista de argumentos. Las claves dentro del objeto «arguments» coinciden, a su vez, con los nombres de los parámetros de la función en la definición de Thrift.
A continuación te ofrecemos un ejemplo de respuesta:
Un ejemplo de una excepción definida en la API que se ha producido:
Ten en cuenta que también puede manejar fácilmente estructuras (y estructuras anidadas dentro de otras estructuras). En el ejemplo anterior, `currentUser` es una estructura. En JSON, se trata simplemente de un objeto JSON cuyas claves coinciden con los nombres de los campos de la definición de la estructura de Thrift.
Además, «err» (la excepción) también es una estructura, ya que en Thrift las excepciones no son más que un tipo especial de estructuras.
Furthermore, note that the success object itself is a struct. Its is an auto generated struct whose name is usually <MethodName>_result (in this case login_result). You can see it if you ever peek into the generated code for any other language. It has two fields: result for a successful call and err for any api defined error that was thrown.
Similarly, the arguments is also an auto generated Struct, usually call <MethodName>_args (in this case login_args). Its fields are simply the function arguments. Thus, this format follows very closely to how actual Thrift works.
Existe un generador de JSON para Thrift que genera todos los metadatos del
- Servicios: nombre, lista de funciones
- Funciones: nombre, lista de argumentos
- Estructuras: nombre, campos junto con sus nombres y tipos
A continuación se muestra un ejemplo de los metadatos generados para el archivo Thrift anterior.
He utilizado estos metadatos dentro de un nuevo protocolo. Un protocolo es la forma en que Thrift marshalla y desmarshalla los datos. El problema es que los protocolos en Thrift son de tipado fuerte. Deben poder transmitir el tipo exacto del campo (o el tipo de elemento del array o el tipo de clave y valor del mapa) y otros datos, como el tamaño del mapa o del array. Por eso el JSONProtocol de Thrift contiene tanta jerga. Transmite exactamente esta información.
Este nuevo protocolo, el HumanReadableJsonProtocol, utiliza el JSON que envía el cliente junto con los metadatos del generador de JSON de Thrift para determinar exactamente qué función se ha llamado, qué argumentos se han enviado y cuáles son sus tipos exactos.
Por ejemplo, en la llamada anterior, primero buscará los metadatos del método de inicio de sesión. A continuación, para cada clave del objeto «arguments»del JSON del cliente, buscará la clave asociada en la matriz «arguments» de los metadatos. Dependiendo del tipo, lo analizará (si se trata de una estructura, una lista o un mapa, seguirá recursivamente hasta llegar a un tipo básico —int, string, boolean, double, etc.). Por ejemplo, en este caso buscará en los metadatos un objeto cuyovalor de «name» sea«email», comprobará que su tipo es String y, a continuación, verificará que el valor de«email» en el objeto «arguments» del JSON del cliente también sea un String. Lo mismo ocurre con«password».
Este nuevo HumanReadableJsonProtocol sigue siendo de tipado fuerte. Si envías una clave cuyo valor no se corresponde correctamente con el tipo definido en los metadatos, se producirá un error.
Este es el error que se produce en un caso así, en el que intenté introducir un número en lugar de una cadena en el campo de la contraseña:
Ten en cuenta que este JSON tiene una clave «exception», mientras que los anteriores tenían una clave «result» seguida de «success» o «error». Esto es similar a cómo Thrift gestiona los diferentes tipos de respuesta: se obtiene un «Result» o una «Exception». «Result» significa que la llamada se ha realizado con éxito y que no se ha producido ningún error , salvo los definidos por la API (los que figuran en la firma del método). Por lo tanto, «Result» tiene dos campos: uno para «success», que contiene el resultado satisfactorio de la llamada, y otro para «error», que contiene el error definido por la API que se ha producido. «Exception» recoge cualquier otro error (incluidos los errores de Thrift, como datos dañados, imposibilidad de analizar los datos, tipos incorrectos, etc.).
Dado que se trata simplemente de un protocolo (una forma de serializar y deserializar datos), el código generado por Thrift que lo utilice se encargará automáticamente de aspectos como los campos obligatorios u opcionales.
Así pues, por ejemplo, si la solicitud tiene un tipo de contenido «application/json», solo tienes que utilizar el protocolo `HumanReadableJsonProtocol` para analizarla; en caso contrario, utiliza el protocolo estándar que suelas emplear. También tendrás que indicar la ruta del directorio donde se encuentran los metadatos JSON generados.
Por último, aplica automáticamente cualquier cambio nuevo en las definiciones de Thrift (siempre y cuando también generes el JSON mediante el generador de JSON).
Aquí está el código fuente del proyecto: HumanReadableJsonProtocol
Si quieres el código de esto o te gustaría ayudar a ampliarlo a más idiomas y a escribir pruebas para él, ponte en contacto conmigo.
Fragmento de código de HumanReadableJsonProtocol en Ruby
Aquí tienes un fragmento del código que realiza el análisis sintáctico en Ruby:
Otra vez me voy a hacer publicidad sin pudor: trabajo en WI (http://wi.co/). Estamos cambiando la forma de trabajar de la gente fuera de Silicon Valley. Si te interesa, echa un vistazo a nuestra página de empleo (http://wi.co/careers) o envíame un correo electrónico a [email protected]











