gRPC vs REST: Comparando enfoques para crear APIs

En el texto de hoy, quiero analizar más de cerca gRPC y REST, probablemente dos de las aproximaciones más comúnmente utilizadas para crear API en la actualidad.

I will start with a short characteristic of both tools — what they are and what they can offer. Then I will compare them according to seven categories, in my opinion, most crucial for modern-day systems.

Las categorías son las siguientes:

  1. Protocolos HTTP subyacentes
  2. Formatos de datos soportados
  3. Tamaño de los datos
  4. Rendimiento
  5. Definiciones
  6. Facilidad de adopción
  7. Soporte de herramientas

El Por Qué

Cuando la gente escucha “API”, probablemente piensa en REST API de inmediato. Sin embargo, REST es solo una de las muchas aproximaciones para construir APIs. No es la solución milagrosa para todos los casos de uso. Existen otras formas, siendo RPC (Llamada a Procedimiento Remoto) solo una de ellas, y gRPC es probablemente el marco más exitoso para trabajar con RPC.

A pesar de ser una tecnología bastante madura y eficiente, gRPC sigue siendo vista como la nueva. Por lo tanto, es menos adoptada que REST a pesar de ser bastante útil en algunos casos de uso.

Mi principal motivo para escribir esta entrada de blog es popularizar gRPC y señalar los casos de uso en los que puede brillar.

¿Qué es REST?

REST, o Representational State Transfer, es probablemente la forma más común de crear una aplicación que expone cualquier tipo de API. Utiliza HTTP como medio de comunicación subyacente. Debido a eso, puede beneficiarse de todas las ventajas de HTTP, como la caché.

Además, siendo stateless por su concepción, REST permite una fácil separación entre cliente y servidor. El cliente solo necesita conocer la interfaz expuesta por el servidor para comunicarse con él de manera efectiva y no depende en ningún sentido de la implementación del servidor. La comunicación entre cliente y servidor se basa en una base de solicitud y respuesta, con cada solicitud siendo una solicitud HTTP clásica.

REST no es un protocolo ni una herramienta (en cierta medida): es un enfoque arquitectónico para construir aplicaciones. Los servicios que siguen el enfoque REST se denominan servicios RESTFul. Como arquitectura, impone varias restricciones a sus usuarios. En particular:

  • Comunicación cliente-servidor
  • Comunicación sin estado
  • Almacenamiento en caché
  • Interfaz uniforme
  • Sistema en capas
  • Código a la demanda

Los dos conceptos cruciales de REST son:

  1. Puntos finales: Una URL única (Uniform Resource Locator) que representa un recurso específico; puede verse como una forma de acceder a una operación o elemento de datos en particular en Internet
  2. Recurso: Una pieza particular de datos disponible bajo una URL específica

Además, existe una descripción llamada el Modelo de Maduración de Richardson, un modelo que describe el grado de “profesionalidad” en las API REST. Divide las API REST en 3 niveles (o 4, dependiendo de si cuentas el nivel 0) según el conjunto de rasgos que una API particular tenga.

Un rasgo es que el punto final REST debe usar sustantivos en la URL y los métodos de solicitud HTTP correctos para gestionar sus recursos.

  • Ejemplo: DELETE user/1 en lugar de GET user/deleteById/1

En cuanto a los métodos HTTP y sus acciones asociadas, es así:

  • GET: Recuperar un recurso específico o una colección de recursos
  • POST: Crear un nuevo recurso
  • PUT: Upsert de todo el recurso
  • PATCH: Actualización parcial de un recurso específico
  • DELETE: Eliminar un recurso específico por id

El modelo de madurez especifica mucho más que eso; por ejemplo, un concepto llamado HiperMedia. HiperMedia une la presentación de datos y el control sobre las acciones que los clientes pueden realizar.

A full description of the maturity model is out of the scope of this blog — you can read more about it here.

Aviso: muchas cosas mencionadas en este párrafo son más matizadas de lo descrito aquí. REST es un tema bastante amplio y merece una serie entera de artículos. Sin embargo, todo lo aquí mencionado está de acuerdo con las mejores prácticas REST comúnmente conocidas.

¿Qué es gRPC?

Es otra implementación del concepto relativamente antiguo de Llamada a Procedimientos Remotos (RPC). La desarrollaron personas de Google, razón por la cual tiene una “g” en su nombre. Es probablemente la herramienta más moderna y eficiente para trabajar con RPC y también un proyecto CNCF incubación.

gRPC utiliza Protocol Buffers de Google como formato de serialización y HTTP/2 como medio de transporte de datos, aunque gRPC también puede funcionar con JSON como capa de datos.

Los bloques de construcción básicos de gRPC incluyen:

  • Método: El bloque de construcción básico de gRPC, cada método es una llamada a procedimiento remoto que toma alguna entrada y devuelve salida. Realiza una sola operación implementada más adelante en el lenguaje de programación de elección. Por el momento, gRPC admite 4 tipos de métodos:
  1. Unario: Modelo clásico de solicitud-respuesta donde el método toma entrada y devuelve salida
  2. Streaming del servidor: Los métodos aceptan un mensaje como entrada y devuelven la secuencia de mensajes como salida. gRPC garantiza el orden de los mensajes dentro de una llamada RPC individual.
  3. Streaming del cliente: El método toma la secuencia de mensajes como entrada, los procesa hasta que no quedan mensajes y luego devuelve un solo mensaje como salida. Similar al anterior, gRPC garantiza el orden de los mensajes dentro de una llamada RPC individual.
  4. Transmisión Bidireccional: El método toma la secuencia como entrada y devuelve la secuencia como salida, utilizando efectivamente dos secuencias de lectura y escritura. Ambas secuencias operan de forma independiente y se conserva el orden de los mensajes a nivel de secuencia.
  • Servicio: Representa un grupo de métodos, cada método debe tener un nombre único dentro del servicio. Los servicios también describen características como seguridad, tiempos de espera o reintentos.
  • Mensaje: Un objeto que representa la entrada o salida de métodos.

Las definiciones de la API gRPC se escriben en forma de archivos .proto que contienen los tres bloques de construcción básicos mencionados anteriormente. Además, gRPC proporciona un compilador de protocol buffers que genera código de cliente y servicio a partir de nuestros archivos .proto.

Podemos implementar métodos del lado del servidor de la manera que deseemos. Debemos atenernos al contrato de entrada-salida de la API.

En el lado del cliente, existe un objeto llamado cliente (o stub) similar a un cliente HTTP. Conoce todos los métodos del servidor y simplemente se encarga de llamar a procedimientos remotos y devolver sus respuestas.

La Comparación

Protocolo HTTP Subyacente

Esta es la primera categoría y probablemente la más importante, ya que su influencia también puede ser visible en otras.

En general, REST es basado en solicitud-respuesta y utiliza HTTP/1.1 como medio de transporte. Debemos usar un protocolo diferente como WebSocket (más información sobre ellos aquí) o cualquier tipo de transmisión o conexión más duradera.

También podemos implementar un código provisional para hacer que REST parezca streaming. Además, usar HTTP/1.1 para REST requiere una conexión por cada intercambio de solicitud-respuesta. Tal enfoque puede ser problemático para solicitudes de larga duración o cuando tenemos capacidades de red limitadas.

Por supuesto, podemos usar HTTP/2 para construir APIs similares a REST; sin embargo, no todos los servidores y bibliotecas pueden soportar HTTP/2 todavía. Por lo tanto, pueden surgir problemas en otros lugares.

Por otro lado, gRPC utiliza solo HTTP/2. Permite enviar múltiples pares de solicitud-respuesta a través de una sola conexión TCP. Tal enfoque puede ser un impulso de rendimiento bastante significativo para nuestra aplicación.

  • Resultado: Ligera ventaja para gRPC

Formatos de Datos Soportados

Suponiendo el caso por defecto cuando la API REST utiliza HTTP/1.1, entonces puede soportar muchos formatos.

REST generalmente no impone restricciones en el formato y estilo del mensaje. Esencialmente, cualquier formato que pueda ser serializado a texto plano antiguo es válido. Podemos usar cualquier formato que nos convenga mejor en un escenario particular.

El formato más popular para enviar datos en aplicaciones REST es sin duda JSON. XML ocupa el segundo lugar debido al gran número de aplicaciones antiguas/legadas.

Sin embargo, cuando se usa REST con HTTP/2, solo se admiten formatos de intercambio binarios. En este caso, podemos usar Protobuf o Avro. Por supuesto, tal enfoque puede tener sus desventajas, pero más sobre esto en los siguientes puntos.

Mientras tanto, gRPC solo soporta dos formatos para el intercambio de datos:

  1. Protobuf – Por defecto
  2. JSON — Cuando necesites integrar con una API antigua

Si decides probar con JSON, entonces gRPC utilizará JSON como formato de codificación para mensajes y GSON como formato de mensaje. Además, utilizar JSON requerirá algo más de configuración. Aquí está la documentación de gRPC sobre cómo hacerlo.

  • Resultado: Victoria para REST, ya que soporta más formatos.

Tamaño de Datos

Por defecto, gRPC utiliza el formato de intercambio de datos binario, lo que REDUCE en gran medida el tamaño de los mensajes enviados a través de la red: investigación indica que es aproximadamente un 40-50% menor en tamaño en bytes — mi experiencia en uno de los proyectos anteriores indica incluso un 50-70% menos.

El artículo anterior proporciona una comparación de tamaño relativamente profunda entre JSON y Protobuff. El autor también proporcionó una herramienta para generar JSON y archivos binarios. De este modo, puedes repetir sus experimentos y comparar los resultados.

Los objetos del artículo son razonablemente simples. Sin embargo, la regla general es — cuanto más objetos anidados y estructura más compleja tenga el JSON, más pesado será en comparación con Protobuf. Una diferencia del 50% en tamaño a favor de Protobuf es una buena línea base.

La diferencia puede minimizarse o eliminarse al utilizar el formato de intercambio binario para REST. Sin embargo, no es la forma más común ni mejor soportada de realizar APIs RESTful, por lo que pueden surgir otros problemas.

  • Resultado: En el caso predeterminado, victoria para gRPC; en el caso de ambos utilizando formato de datos binarios, un empate.

Rendimiento

Nuevamente, en el caso de REST, todo depende del protocolo HTTP subyacente y del servidor.

En el caso predeterminado, REST basado en HTTP/1.1, incluso el servidor más performante no podrá superar el rendimiento de gRPC, especialmente cuando agregamos la sobrecarga de serialización y deserialización al utilizar JSON. Aunque cuando cambiamos a HTTP/2 la diferencia parece disminuir.

En cuanto al rendimiento máximo, en ambos casos, HTTP es un medio de transporte, por lo que tiene el potencial de escalar hasta el infinito. Así que todo depende de las herramientas que estemos utilizando y qué estamos haciendo exactamente con nuestra aplicación, ya que no hay límites por diseño.

  • Resultado: En el caso predeterminado, gRPC; en el caso de ambos utilizando datos binarios y HTTP/2, empate o leve victoria para gRPC.

Definiciones

En esta parte, describiré cómo definimos nuestras mensajes y servicio en ambos enfoques.

En la mayoría de las aplicaciones REST, simplemente declaramos nuestras solicitudes y respuestas como clases, objetos o cualquier estructura que admita un lenguaje en particular. Luego confiamos en las bibliotecas proporcionadas para la serialización y deserialización de JSON/XML/YAML, o cualquier formato que necesitemos.

Además, existen esfuerzos continuos para crear herramientas capaces de generar código en el lenguaje de programación de elección a partir de definiciones de API REST de Swagger. Sin embargo, parecen estar en la versión alfa, por lo que aún pueden surgir algunos errores y problemas menores que los hagan difíciles de usar.

No hay mucha diferencia entre los formatos binarios y no binarios para aplicaciones REST, ya que la regla es más o menos la misma en ambos casos. Para el formato binario, simplemente definimos todo de la manera requerida por un formato en particular.

Además, definimos nuestro servicio REST mediante métodos o anotaciones de nuestra biblioteca o framework subyacente. La herramienta también es responsable de exponerlo junto con otras configuraciones al exterior.

En el caso de gRPC, tenemos Protobuf como predeterminado y de facto la única forma de escribir definiciones. Tenemos que declarar todo: mensajes, servicios y métodos en archivos .proto, por lo que el asunto es bastante sencillo.

Luego usamos la herramienta proporcionada por gRPC para generar código para nosotros, y solo tenemos que implementar nuestros métodos. Después de eso, todo debería funcionar como se pretende.

Además, Protobuf admite la importación, por lo que podemos distribuir nuestra configuración en múltiples archivos de una manera razonablemente sencilla.

  • Resultado: No hay ganador aquí, solo la descripción y un consejo de mi parte: elige el enfoque que más se adapte a tus necesidades.

Facilidad de Adopción

En esta parte, compararé el soporte de la biblioteca/framework para cada enfoque en los lenguajes de programación modernos.

En general, cada lenguaje de programación (Java, Scala, Python) que he encontrado en mi corta carrera como ingeniero de software cuenta con al menos 3 bibliotecas/marcos principales para crear aplicaciones con estilo REST, sin mencionar un número similar de bibliotecas para analizar JSON a objetos/clases.

Además, dado que REST utiliza formatos legibles por humanos de manera predeterminada, es más fácil de depurar y trabajar con para los recién llegados. Esto también puede influir en la paz de entregar nuevas características y ayudarlo a combatir errores que aparecen en su código.

En resumen, el soporte para aplicaciones de estilo REST es al menos muy bueno.

En Scala, incluso tenemos una herramienta llamada tapir — de la cual tuve el placer de ser uno de los mantenedores durante un tiempo. Tapir nos permite abstraernos del servidor HTTP y escribir puntos finales que funcionarán para varios servidores.

gRPC por sí solo proporciona una biblioteca de cliente para más de 8 lenguajes de programación populares. Por lo general, es suficiente, ya que estas bibliotecas contienen todo lo necesario para crear una API gRPC. Además, conozco bibliotecas que proporcionan abstracciones más altas para Java (a través de Spring Boot Starter) y para Scala.

Otra cosa es que REST se considera hoy en día un estándar mundial y un punto de entrada para la construcción de servicios, mientras que RPC y gRPC, en particular, aún se ven como algo novedoso a pesar de ser algo antiguos en este punto.

  • Resultado: REST, ya que es más ampliamente adoptado y cuenta con muchas más bibliotecas y frameworks alrededor

Soporte de Herramientas

Las bibliotecas, frameworks y la cuota de mercado general se cubrieron anteriormente, por lo que en esta parte, me gustaría abordar las herramientas que rodean ambos estilos. Significa herramientas para pruebas, pruebas de rendimiento/estrés y documentación.

Pruebas Automatizadas/Pruebas

Primero, en el caso de REST, las herramientas para construir pruebas automatizadas están integradas en diferentes bibliotecas y frameworks o son herramientas separadas construidas con este único propósito, como REST-assured.

En el caso de gRPC, podemos generar un stub y usarlo para pruebas. Si queremos ser aún más estrictos, podemos usar el cliente generado como una aplicación separada y usarlo como base para nuestras pruebas en el servicio real.

En cuanto al soporte de herramientas externas para gRPC, estoy al tanto de:

  • Aplicación Postman soporte para gRPC
  • El cliente HTTP de JetBrains usado en sus IDE también puede soportar gRPC con alguna configuración mínima

  • Resultado uno: Victoria para REST; sin embargo, la situación parece mejorar para gRPC.

Pruebas de Rendimiento

Aquí, REST tiene ventajas significativas, ya que herramientas como JMeter o Gatling facilitan en gran medida la prueba de estrés de las API REST.

Lamentablemente, gRPC no cuenta con tal soporte. Sé que las personas de Gatling han incluido el plugin gRPC en la versión actual de Gatling, por lo que la situación parece estar mejorando.

Sin embargo, hasta ahora, solo teníamos un plugin y biblioteca no oficial llamado ghz. Todas estas son buenas; simplemente no es el mismo nivel de soporte que para REST.

  • Resultado dos: Victoria para REST; sin embargo, la situación parece mejorar para gRPC, nuevamente 😉

Documentación

En el caso de la documentación de API, la victoria es nuevamente para REST con OpenAPI y Swagger siendo ampliamente adoptados en la industria y siendo el estándar de facto. Casi todas las bibliotecas para REST pueden exponer documentación de swagger con poco esfuerzo o simplemente fuera de la caja.

Lamentablemente, gRPC no tiene nada parecido a esto.

Sin embargo, la pregunta es si gRPC necesita una herramienta como esta en absoluto. gRPC es más descriptivo que REST por diseño, por lo que las herramientas de documentación adicionales pueden.

En general, los archivos .proto con nuestra descripción de API son más declarativos y compactos que el código responsable de hacer que nuestro código de API REST, por lo que tal vez uno no necesite más documentación de gRPC. La respuesta la dejo a tu criterio.

  • Resultado tres: Victoria para REST; sin embargo, la cuestión de la documentación de gRPC sigue abierta.

Resultado general:

A significant victory for REST


Resumen

La tabla de puntuación final se ve así.


Las puntuaciones están igualadas entre ambos estilos, con tres victorias cada uno y una categoría sin un ganador claro.

No hay una solución mágica: solo piensa en qué categorías pueden ser las más importantes para tu aplicación y luego elige el enfoque que ganó en la mayoría de ellas, al menos esa es mi recomendación.

En cuanto a mi preferencia, probaré gRPC si puedo, ya que funcionó bastante bien en mi último proyecto. Puede ser una mejor opción que el viejo compañero REST.

Si alguna vez necesitas ayuda para elegir entre REST y gRPC o lidiar con cualquier otro tipo de problema técnico, avísame. Tal vez pueda ayudar.

Gracias por tu tiempo.

Source:
https://dzone.com/articles/grpc-vs-rest-comparison