gRPC: pionero de la comunicación cliente-servidor del futuro

La tecnología de las redes sigue avanzando a una velocidad de vértigo. Con el objetivo de cumplir las demandas cada vez más exigentes de los sistemas informáticos distribuidos, se ha desarrollado un nuevo sistema denominado gRPC para las Remote Procedure Calls o llamadas a procedimiento remoto. La “g” es de Google, ya que la empresa jugó un papel determinante en el desarrollo del sistema. Te explicamos qué es gRPC, cómo funciona y dónde se utiliza.

¿Qué es gRPC?

gRPC es un moderno sistema de llamada a procedimiento remoto que procesa la comunicación en estructuras cliente-servidor distribuidas de manera especialmente eficiente gracias a una innovadora ingeniería de procesos. Actúa en el nivel del proceso, al igual que su antecesor, el sistema RPC. Un elemento característico de la comunicación entre procesos mediante gRPC es el principio de transparencia: la colaboración entre instancias (en parte muy) distanciadas es tan estrecha y sencilla que no se percibe ninguna diferencia en comparación con una comunicación local entre procesos internos de una máquina.

Desarrollado por Google en el año 2015, hoy es la Cloud Native Computing Foundation la encargada de su distribución y desarrollo. gRPC es un elemento de código abierto, es decir, el código fuente está accesible para que otros desarrolladores hagan modificaciones y participen en su desarrollo.

Por defecto, gRPC ejecuta el transporte de flujos de datos entre ordenadores alejados mediante HTTP/2 y gestiona la estructura y la distribución de los datos mediante los Protocol buffers desarrollados por Google. Estos últimos se guardan en forma de archivos de texto plano con la extensión .proto.

A menudo, gRPC se define como un tipo de framework. Una de las características destacadas de los frameworks es que proporcionan un marco de programación a los desarrolladores para ahorrar tiempo y trabajo. La estructura estandarizada de gRPC ya incluye diferentes funciones y elementos que no hay que programar una y otra vez cada vez que se necesitan. El marco gRPC define además interfaces normalizadas para acceder a determinadas fuentes (p. ej., bases de datos).

Así funciona gRPC: multilingüe y eficiente gracias a Protocol Buffers y HTTP/2

Los Protocol Buffers (Protobuf) cumplen varias funciones en el sistema gRPC: sirven como lenguaje de descripción de interfaz (Interface Definition Language, IDL) y describen una interfaz de manera independiente de cualquier lenguaje, es decir, no están vinculados a un lenguaje de programación específico (p. ej., Java o C). También definen los servicios que se deben emplear y las funciones disponibles. Para cada función, puede indicarse qué parámetros se envían con una consulta y qué valor de respuesta se puede esperar.

Desde la perspectiva remota, los Protocol Buffers sirven como el formato subyacente de intercambio de mensajes que determina las estructuras, los tipos y los objetos de los mensajes. Son los elementos que hacen que el cliente y el servidor se “entiendan” y que funcionen como una unidad funcional y lo más eficiente posible, incluso a gran distancia.

El proceso de una solicitud gRPC en caso de una consulta de base de datos (p. ej., “búsqueda de stock de un artículo en el almacén”) sería el siguiente:

  • Antes de que se pueda llevar a cabo la búsqueda, hay que realizar ciertos preparativos. En el lado del servidor, primero se implementan un servicio y un servidor gRPC sobre la base de los Protocol Buffers. El cliente que hace la consulta, por su parte, genera el stub correspondiente. Si está disponible, la aplicación de cliente llama a la función correspondiente (“consulta de búsqueda de stock de un artículo”) en el stub.
  • A continuación, la consulta se envía al servidor a través de la red. Una vez recibida la consulta con ayuda de una interfaz de servicio adecuada, es cuando el servidor gRPC inicia la búsqueda real del producto en la base de datos.
  • Entonces el servidor envía una respuesta al stub del cliente que, a su vez, transmite el valor de respuesta a la instancia de consulta original (p. ej., “número de artículos encontrados”).

Tanto las aplicaciones del lado del cliente, como las del lado servidor, se pueden escribir en diferentes lenguajes de programación. gRPC es capaz de superar estas barreras mediante interfaces y mecanismos de traducción especiales.

Para el transporte de ida y vuelta de los flujos de datos entre máquinas (Proto Request y Proto Response) se integra HTTP/2 en protocolos de red específicos como TCP/IP o UDP/IP. Los flujos transmiten datos binarios compactos que surgen en la serialización (marshalling) típica de las llamadas a procedimientos remotos. Para procesar estas estructuras de datos, totalmente abstractas, en los pasos siguientes en el lado del servidor y en el lado del cliente, el contenido transmitido se vuelve a deserializar (unmarshalling).

El flujo de trabajo gRPC y primeros pasos con Protocol Buffers

El flujo de trabajo gRPC se divide en cuatro pasos:

  1. Definición del contrato de servicio para la comunicación entre procesos: se determinan los servicios que se deben aplicar y los parámetros y tipos de respuesta básicos a los que se puede acceder de manera remota.
  2. Generación del código gRPC del archivo .proto: unos compiladores especiales (herramientas de líneas de comandos denominadas “protoc”) generan el código operativo con las clases correspondientes para un lenguaje de destino deseado (p. ej., C++, Java) a partir de los archivos .proto guardados.
  3. Implementación del servidor en el lenguaje deseado.
  4. Creación del stub del cliente que llama al servicio; a continuación, entre el servidor y el cliente se procesan las consultas.

En el caso de una consulta de base de datos para determinar las existencias de un artículo en un almacén (inventory), los primeros pasos a seguir en la sintaxis actual de Protocol Buffer (versión: proto3) serían los siguientes:

syntax = "proto3";
package grpc_service;
import "google/protobuf/wrappers.proto";
service InventoryService {
	rpc getItemByName(google.protobuf.StringValue) returns (Items);
	rpc getItemByID(google.protobuf.StringValue) returns (Item);
	 rpc addItem(Item) returns (google.protobuf.BoolValue);
}
 
message Items {
  string itemDesc = 1;
  repeated Item items = 2;
}
 
message Item {
	string id = 1;
	string name = 2;
	string description = 3;
}

En el ejemplo, la consulta de base de datos emplea “bibliotecas wrapper” especiales del framework gRPC que ya ponen a disposición procesos relevantes de traducción de manera predefinida y se importan al inicio. En estructuras cliente-servidor multilingües y desiguales, estas bibliotecas permiten que interfaces en principio incompatibles puedan comunicarse. Así es como se generan, p. ej., las clases necesarias para leer y escribir mensajes.

El siguiente gráfico muestra cómo la definición de servicio (inventory.proto) regula la consulta de una base de datos en una estructura cliente-servidor:

HTTP/2: streaming optimizado

HTTP/2 desempeña un papel determinante para gRPC, ya que permite la transferencia de datos binarios compactos para aportar mayor eficiencia al intercambio de mensajes y datos. El protocolo proporciona cuatro variantes para llamadas a procedimiento remoto:

1. Las RPC unarias representan el patrón gRPC más sencillo, por el cual el cliente envía una sola solicitud al servidor y, como en una llamada normal a una función, solo obtiene una respuesta.

Ejemplo: rpc SayHello (HelloRequest) responde (HelloResponse)

2. Las RPC de streaming de servidor permiten un intercambio más complejo de mensajes dentro de una única llamada RPC. Primero, el cliente envía una solicitud al servidor. Entonces recibe como respuesta un hilo (stream) con una larga secuencia de mensajes (solicitud eficiente de mensajes dentro de una sola llamada RPC). A continuación, el cliente lee el hilo hasta que no queden mensajes.

Ejemplo: rpc LotsOfReplies (HelloRequest) responde (stream HelloResponse)

3. Las RPC de streaming de cliente invierten el proceso: el cliente escribe una secuencia de mensajes y la envía al servidor vía stream. Una vez que el cliente ha preparado los mensajes, espera a que el servidor los lea y le responda. En este caso, la solicitud de mensajes también se realiza dentro de una sola llamada RPC.

Ejemplo: rpc LotsOfGreetings (stream HelloRequest) responde (HelloResponse)

4. Las RPC de streaming bidireccional representan la forma más compleja de comunicación, en la cual ambos lados envían una secuencia de mensajes. Ambos streams de datos trabajan de manera independiente entre sí, de manera que el cliente y el servidor pueden leer y escribir sin importar el orden. De esta manera, el servidor puede esperar a que entren todos los mensajes del cliente antes de redactar sus respuestas, pero también puede escribir y leer mensajes de manera alterna. También se permite cualquier otra combinación de procesos de lectura y escritura.

Por ejemplo: rpc BidiHello (stream HelloRequest) responde (stream HelloResponse)

Gracias a las solicitudes anidadas, las variantes 2 a 4 permiten una multiplexación especialmente eficiente en la que en una sola conexión TCP se agrupan varias señales que se pueden transmitir de manera simultánea por la red. Los bloqueos del tráfico de datos se superan mediante el potente protocolo HTTP/2.

Ventajas y desventajas de gRPC

gRPC cuenta con numerosas ventajas: la tecnología es fácil de aplicar, ya que, al crear los archivos .proto, emplea un IDL sencillo, fácil de aprender. Con él, incluso los programas anticuados pueden ampliarse con una potente interfaz gRPC, de forma que puedan transmitir archivos grandes notablemente más rápido.

gRPC ha sido probado en múltiples ocasiones y es fácilmente escalable, por lo que también se puede aplicar en comunicaciones más complejas y amplias, p. ej., en estructuras cliente-servidor interconectadas a nivel global. Aquí, HTTP/2 no solo aumenta la eficiencia gracias a la multiplexación y el streaming bidireccional, sino que también permite comprimir los encabezados para reducir el volumen de datos de las solicitudes y respuestas en la red de manera notable.

La estructura en capas, fuertemente estandarizada, del framework gRPC permite reducir el esfuerzo de programación. De esta forma, los desarrolladores pueden centrar toda su atención en la aplicación de los métodos. Si se requieren adaptaciones, los programadores y desarrolladores de sistemas puedan aprovechar el acceso libre al código fuente.

Además, los Protocol Buffers y los compiladores Protobuf permiten una comunicación que trasciende las fronteras: los sistemas operativos diferentes, los componentes dispares de estructuras cliente-servidor y los lenguajes de programación diferentes ya no representan un problema. Así, un software escrito en C puede comunicarse con un software de Java, por ejemplo. Hoy en día, hay disponibles compiladores Protobuf para un gran número de lenguajes, p. ej., para C#, C++, Go, Objective-C, Java, Python, Node.js, Android Java, Swift, Ruby y PHP.

La flexibilidad de gRPC representa otra ventaja. También se puede usar para el intercambio de datos de microservicios o de aplicaciones móviles que comparten sus datos con servidores. Más ventajas: el protocolo permite la aplicación de tecnologías modernas de seguridad. gRPC cuenta con una autenticación integrada y fomenta el uso de SSL/TLS para la autenticación y la codificación del intercambio.

En la otra cara de la moneda, actualmente, las pruebas de las interfaces gRPC todavía cuentan con mucho margen de mejora. Los mensajes gRPC codificados con Protobuf no son legibles sin ayuda técnica. Por lo tanto, al analizar el tráfico de datos y, sobre todo, en la localización y solución de errores (debug) hay que usar instancias adicionales para transmitir el código de forma legible para detectar los errores. La interconexión de estructuras cliente-servidor distribuidas implica más desventajas. Al conectar ordenadores a través de largas distancias, gRPC está mucho más expuesto que un sistema local. Depende de una red estable y potente y de que la red, el tráfico de datos, los protocolos de transmisión y el cliente y el servidor no se conviertan en presa fácil de los hackers. Otra desventaja es que gRPC no es compatible con el multicasting.

Comparativa entre gRPC y REST

Gracias a sus ventajas, gRPC representa una alternativa competente a REST (Representational State Transfer). REST es especialmente adecuado para servicios más sencillos, mientras que gRPC desarrolla todo su potencial en las interfaces complejas (API). Por norma general, para el intercambio de datos entre aplicaciones, REST usa el formato de datos JSON, un formato con base textual, por lo que supone una gran carga para los recursos de la red.

El sistema gRPC, en cambio, es capaz de organizar un flujo de datos mucho más compacto gracias a los Protocol Buffers y HTTP/2. De esta manera, el espacio de memoria requerido para la serialización y binarización se reduce en casi un 70 por ciento en comparación con, por ejemplo, el sistema JSON. Además, el streaming bidireccional, que funciona sin generar bloqueos en el intercambio de datos, aporta enormes ventajas de potencia y velocidad en comparación con REST.

Actualmente, su cooperación con aplicaciones web todavía deja mucho que desear, ya que no suelen estar optimizadas para el uso de búferes de registro, el paradigma “contrato primero” característico de gRPC para el que sí están optimizadas las API Contract First del framework gRPC. Uno de los grandes problemas del trabajo conjunto con aplicaciones web es que aún no es posible acceder a un servicio gRPC directamente desde un navegador. REST no cuenta con estas desventajas, ya que, en contraposición al protocolo HTTP/2, más moderno, HTTP es compatible con todos los navegadores, si bien es cierto que este contratiempo se puede compensar con un esfuerzo asumible, de manera que se puede usar el mismo servicio para una aplicación web y para una aplicación móvil. Una opción viable en este ámbito es gRPC-Web. Los desarrolladores gRPC siguen trabajando para encontrar más soluciones que faciliten la colaboración de gRPC con herramientas basadas en la web.

¿En qué casos se usa gRPC?

El sistema gRPC es especialmente adecuado para una comunicación eficiente entre procesos en estructuras cliente-servidor distribuidas que busquen una latencia baja y un flujo elevado de datos y mensajes. gRPC se usa con frecuencia en y entre centros de datos alejados para conectar servicios o microservicios entre sí. Como las herramientas gRPC son compatibles con los lenguajes de desarrollo más comunes, es muy frecuente que se usen en entornos multilingües.

La velocidad, la eficiencia y su carácter multilingüe favorecen el uso de gRPC en el ámbito móvil y la comunicación con aplicaciones. El gRPC regula, sobre todo, el último tramo del procesamiento distribuido de datos, ya que conecta los dispositivos, las aplicaciones móviles y los navegadores con servicios backend.

Además, el potente streaming a través de HTTP/2 lo predestina para la comunicación punto a punto en tiempo real. El Internet of things y la domótica se benefician de este procedimiento respetuoso con los recursos, ya que cada vez se ocupa más de la comunicación de clientes de bajos recursos. Debido a su potencia y dado que es fácil de desarrollar, esta tecnología de comunicación podría desempeñar un papel destacado en la nube en el futuro y contrarrestar, así, la hegemonía actual de REST. En la actualidad, gRPC también se maneja como alternativa al XML (Extensible Markup Language).

Nota

El XML es un formato de uso frecuente para intercambiar datos o guardar información de manera estructurada.