Comprender gRPC, OpenAPI y REST, y cuándo usarlos en el diseño de API (2020)
(cloud.google.com)- El punto de partida del diseño de API es la diferencia entre RPC y REST; los tres enfoques pueden vincularse con HTTP, pero difieren en el modelo para crear llamadas y estructurar clientes.
- REST es un modelo de hipertexto en el que se siguen las URL proporcionadas por el servidor, por lo que se distingue de las API al estilo OpenAPI, donde el cliente compone formatos de URL.
- OpenAPI define operaciones mediante plantillas de rutas URL y métodos HTTP; es práctico y muy usado, pero se acerca más a un modelo RPC mapeado sobre HTTP que a REST.
- gRPC define API RPC directamente mediante IDL, generación de código, payloads binarios y gestión de conexiones HTTP/2, ocultando los detalles de HTTP.
- gRPC requiere software especial en ambos lados y tiene limitaciones en enriquecimiento mediante proxies, prevención de actualizaciones concurrentes y actualizaciones parciales, por lo que es especialmente adecuado para API internas o cuando se puede usar una capa de conversión como Cloud Endpoints.
Tres modelos para ver las API basadas en HTTP
- Las formas representativas de usar HTTP como capa de transporte de API se dividen en REST, OpenAPI y gRPC.
- Una de las razones por las que muchas API públicas y API distribuidas privadas usan HTTP es que las organizaciones están familiarizadas con los problemas de seguridad del tráfico HTTP en los puertos 80 y 443.
- Los tres enfoques pueden conectarse con HTTP, pero difieren en qué toman como dirección y en cómo el cliente construye las llamadas.
REST: seguir URL, no componerlas
- En REST, el cliente usa tal cual las URL que entrega el servidor, y no entiende ni compone el formato de las URL como parte de la especificación de la API.
- Un navegador sigue la página actual, los marcadores y las URL ingresadas por el usuario, y apenas extrae información de solicitud HTTP desde la URL o convierte URL relativas en absolutas.
- El núcleo de una API REST es el uso de hipertexto/hipermedia para expresar las referencias entre recursos como URL de otros recursos.
- En el enfoque REST, todos los identificadores se intercambian como URL.
POST /accounts→account_URLPOST /subscriptionsconaccount_URL→subscription_URLGET {account_URL}→ devuelve el árbol de datos de la cuenta
- Las ventajas de REST se acercan a la estabilidad, coherencia y universalidad de la web misma, y el modelo orientado a entidades de HTTP/REST puede hacer que una API sea más simple y regular.
OpenAPI: más cercano a RPC mapeado directamente sobre HTTP
- OpenAPI define plantillas de rutas URL bajo
paths, y llama operación (operation) a la combinación de una ruta y un método HTTP. - Una ruta como
/pets/{petId}exige que el cliente conozca el valor de{petId}y lo inserte en la plantilla de URL para construir la solicitud HTTP. - En este enfoque, el cliente debe conocer en detalle el formato de la URL, por lo que es lo opuesto al modelo de hipertexto de REST.
- Las razones por las que OpenAPI se usa ampliamente son claras:
- Es similar al modelo RPC tradicional, por lo que resulta familiar para los programadores.
- Los conceptos de RPC pueden mapearse directamente a solicitudes HTTP.
- En las API públicas, una gran ventaja es que se puede acceder a ellas desde casi cualquier lenguaje y entorno usando solo tecnologías HTTP estándar.
- A cambio, hay que diseñar el mapeo de rutas URL, métodos HTTP y parámetros, por lo que aumentan los detalles que tanto proveedores como consumidores de la API deben aprender.
gRPC: una tecnología de implementación RPC que oculta HTTP/2
- gRPC usa HTTP/2 como capa de transporte, pero no expone los detalles de HTTP al diseñador de la API ni al código del cliente y del servidor.
- El flujo de llamada de un cliente gRPC es simple:
- Decide qué procedimiento llamar.
- Calcula los valores de parámetros que usará.
- Pasa los parámetros a un stub generado por código y realiza la llamada.
- gRPC define procedimientos remotos con base en un interface description language, por lo que no hace falta expresar también el mapeo de rutas URL, parámetros y métodos HTTP como en OpenAPI.
- Mediante generación de código, frameworks y bibliotecas, puede facilitar la creación de bibliotecas cliente e implementaciones de servidor.
- Aprovecha payloads binarios y la gestión de conexiones HTTP/2 para obtener ventajas de rendimiento; las mismas tecnologías también podrían usarse directamente sin gRPC, pero requerirían aprender más aspectos técnicos.
Cuándo considerar gRPC en lugar de OpenAPI
- Al diseñar una API con OpenAPI, hay que expresar operaciones y parámetros como combinaciones de rutas URL y métodos HTTP, y la cantidad de opciones puede volverlo complicado.
- Si se sigue usando un modelo de estilo RPC, gRPC reduce la carga de diseñar directamente un mapeo personalizado sobre HTTP.
- gRPC y OpenAPI tienen modelos de API básicos similares, pero difieren en cómo exponen HTTP:
- OpenAPI expone al cliente los detalles del transporte HTTP y permite al diseñador controlar el mapeo.
- gRPC oculta los detalles de HTTP mediante mapeos predefinidos y código generado.
- La gran ventaja de OpenAPI es que los clientes pueden usar herramientas y tecnologías HTTP estándar tal cual; para muchos diseñadores de API, esta ventaja justifica el costo adicional de diseño.
Combinar un modelo orientado a entidades con RPC
- Aunque se use gRPC u OpenAPI, limitar los métodos RPC a un enfoque centrado en entidades permite obtener algunas ventajas de REST.
- La idea es no empezar por definir procedimientos, sino definir primero tipos de recursos y luego asociar a cada tipo operaciones estándar de entidad.
- Las operaciones básicas son Create, Retrieve, Update, Delete y List, lo que suele verse como CRUD plus List.
- Se pueden agregar operaciones adicionales si hace falta, pero si se mezclan conceptos orientados a entidades con conceptos orientados a procedimientos, algunas ventajas pueden debilitarse.
- Agrupar procedimientos por tipo de entidad también es una de las ideas centrales de los lenguajes orientados a objetos.
Limitaciones y precauciones de gRPC
- gRPC requiere software especial tanto en el cliente como en el servidor, y el código generado debe integrarse en los procesos de build de ambos lados.
- Para usuarios de lenguajes dinámicos como JavaScript o Python, donde puede haber poco o ningún proceso de build en el entorno de desarrollo, este requisito puede ser una carga.
- Google Cloud Endpoints permite acceder a una API gRPC mediante HTTP y JSON, restaurando opciones para el cliente, pero no todos los usuarios pueden usarlo o construir una funcionalidad equivalente.
- Con una API REST es fácil crear un bot que la recorra completa incluso sin metadatos, pero las API de estilo RPC como gRPC u OpenAPI requieren API distintas por tipo de entidad y metadatos o software a medida.
- Las API HTTP suelen agregar funciones de seguridad, validación de entradas, mapeo de formatos de datos y modificaciones de encabezados o cuerpo mediante herramientas de gestión de API y proxies como Apigee Edge, pero en gRPC este enriquecimiento mediante proxies puede ser mucho más difícil.
- gRPC no define un mecanismo estándar para evitar la pérdida de datos por actualizaciones concurrentes.
- HTTP proporciona para esto los encabezados
EtageIf-Match.
- HTTP proporciona para esto los encabezados
- gRPC tampoco define un mecanismo de actualización parcial.
- HTTP tiene
PATCH, y para JSON existen los estándares JSON merge patch y JSON patch. - JSON merge patch es más simple, pero no cubre todos los casos, como actualizaciones de arrays.
- JSON patch cubre más casos, pero es más complejo de usar.
- HTTP tiene
Criterios de elección
- Si ya sabes diseñar el modelo de hipertexto REST o estás dispuesto a aprenderlo, puede ser una buena opción cuando se busca estabilidad, coherencia y universalidad.
- OpenAPI permite crear API accesibles solo con tecnologías HTTP estándar, pero aumenta las opciones de diseño para mapear conceptos RPC sobre HTTP, lo que puede dificultar el diseño, la implementación y el aprendizaje.
- Si estás considerando una API con OpenAPI, también vale la pena evaluar gRPC. Los modelos básicos de API de ambos enfoques son comparables, y gRPC reduce la necesidad de crear manualmente el mapeo HTTP.
- gRPC resulta especialmente atractivo en estas condiciones:
- Cuando productos como Cloud Endpoints permiten que el cliente no tenga que adoptar necesariamente tecnologías gRPC.
- Cuando se trata de una API interna en la que puedes controlar las elecciones tecnológicas del servidor y de todos los clientes.
- Al adoptar gRPC en lugar de OpenAPI o REST, conviene considerar que las oportunidades de enriquecer o corregir el comportamiento de la API mediante proxies basados en herramientas de gestión de API como Apigee Edge pueden ser mucho más limitadas.
1 comentarios
Opiniones de Hacker News
Si pudiera volver el tiempo atrás, hasta querría impedirme aprender gRPC desde el principio.
Al inicio me atrapó su visión, pero después de unos años resultó tener demasiados dolores de cabeza. Eso de que oculta la complejidad interna suena casi a broma, y terminas generando montones de logs de depuración para encontrar la causa de solicitudes que fallan 1 de cada 10 veces, ajustando entre 10 y 20 configuraciones de timeouts/reintentos con nombres poco claros.
Todo me hizo perder tiempo: plugins de Maven, extraños
deadline exceeded, balanceadores de carga que odian HTTP/2, situaciones en las que por los firewalls terminas teniendo que usar una API estándar, documentación pobre, e incluso conseguir mensajes de error útiles para observabilidad.La experiencia de desarrollo con el código generado es mala; los stubs de cliente son clases concretas
final, por lo que es difícil hacer mocks en pruebas, y la implementación del servidor también tiene que heredar de una clase concreta en vez de implementar una interfaz.Los métodos del servidor tienen firmas asíncronas, así que rompen comportamientos basados en AOP como
@Transactional; tampoco hay soporte para excepciones, y aunque las clases de valores inmutables están bien, todo hay que construirlo con builders.Al final, si quieres usar gRPC en SOA, tienes que escribir mucho código de plomería para ocultar el ruido de gRPC y obtener código limpio y testeable, y el compilador RPC de Thrift tiene problemas similares más otros adicionales.
En .NET moderno y C#, la experiencia con gRPC es bastante buena; Microsoft incluso retiró tecnologías RPC previas como WCF y se enfocó en gRPC.
protocera más verboso y propenso a errores que serializar directamente.El protocolo de cable no es type-safe; tiene etiquetas de tipo, pero reutiliza la misma etiqueta para varios tipos de datos. La codificación de enteros zig-zag también es lenta.
Como biblioteca RPC es pésima, y de lo que he usado directamente, lo único peor fue FlatBuffers.
Me pregunto si esta diferencia se debe a Java o a la tecnología gRPC en sí.
Me pregunto si son problemas específicos de Java+gRPC.
Llevo mucho tiempo creando APIs, he usado tanto gRPC como HTTP/REST, y también publiqué la biblioteca https://github.com/oapi-codegen/oapi-codegen, que genera clientes y servidores en Go a partir de especificaciones OpenAPI.
Me cuesta estar de acuerdo con la forma en que el artículo distingue OpenAPI de REST. OpenAPI es una forma de documentar el comportamiento de una API HTTP, y puede representar tanto una API RESTful como una API completamente arbitraria. En el sentido de que es un lenguaje de esquema para describir una API de manera que las herramientas puedan interpretarla, conceptualmente se parece a los archivos Protocol Buffer que especifican el protocolo gRPC.
gRPC es un mecanismo RPC que intercambia proto; cuando Google abrió protobuf, no abrió Stubby, su capa RPC interna, y gRPC no es tan bueno como Stubby. Aun así, es eficiente en transporte y relativamente fácil de extender.
Sin embargo, gRPC no tiene un ecosistema tan sólido como las bibliotecas HTTP más populares, por lo que muchas veces hay que implementar middleware como logging o autenticación por cuenta propia, especialmente en RPC entre servicios implementados en distintos lenguajes.
Creo que el verdadero problema de gRPC son los archivos proto. Todos los clientes deben compilarse con archivos
.protocompatibles con el servidor, así que no es un protocolo descubrible. Una API HTTP puede invocarse concurlo con código escrito directamente incluso sin una descripción OpenAPI, lo que la hace menos acoplada y, por eso, más fácil de trabajar y depurar.REST, tal como lo definió Roy Fielding en su tesis doctoral de 2000, implicaba que al hacer
GETa la URL raíz hubiera enlaces dentro de una respuesta200 OK, y que siguiendo esos enlaces se pudieran explorar todos los recursos que ofrece la API. Se permitía una estructura jerárquica, pero todo debía ser accesible desde algún punto del árbol de enlaces; la intención era aportar descubribilidad.En casi todos los lugares donde trabajé durante los últimos 20 años se usaba
POST resource_name/resource_id/sub_resource/sub_resource_id/mutation_typeo, según la forma de manejar la idempotencia de la empresa,PUT resource_name/resource_id/sub_resource/sub_resource_id, y el cliente armaba URLs mágicas basándose en conocimiento estructural como Swagger/OpenAPI.Por eso, la gente más estricta suele llamar a esa práctica “RESTful” y no “REST”, para indicar que no implementa la definición de REST de Fielding.
Desde la posición de administrar APIs bastante grandes con clientes internos y externos, también me cuesta entender el flujo de generar código desde una especificación OpenAPI. Si llenas los stubs generados y luego iteras la especificación de la API, la herramienta vuelve a crear nuevos stubs, se vuelve necesario fusionar manualmente, y mientras más crece la API, más difícil se hace encontrar los cambios relacionados.
Por eso terminé creando un monstruo que genera la especificación OpenAPI a partir del código usando
go/asty similares. No es perfecto, pero es una solución al 95% que funciona tanto con Echo como con Gin; si hace falta un endpoint nuevo, puedo crear las structs de request/response y un handler vacío, generar la documentación y enviársela al desarrollador frontend, avanzando rápido.La mayoría de los desarrolladores no necesita pensar en cómo expresar la API con OpenAPI, y la documentación siempre coincide con el código.
Apipe.new(GitHun) |> from("search/repositories") |> eq(:language, "elixir") |> order_by(:updated) |> limit(1) |> execute()No hace falta conocer las funciones gRPC disponibles ni las particularidades RESTful de APIs de terceros, y se conservan la documentación integrada y el acceso tipado.
https://github.com/cpursley/apipe
También estoy considerando una capa adaptadora para TypeScript, para poder incorporarlo en proyectos JS/TS al estilo Supabase.
const { data, error } = await apipe.from('search/repositories').eq('language', 'elixir').order_by('updated').limit(1)Esta llamada puede pasar por un proxy en Elixir y delegarle tareas pesadas como procesamiento asíncrono o rate limiting.
Se puede crear una descripción OpenAPI basada en la serialización JSON de Protobuf y ofrecerla con Swagger; además, gRPC en sí proporciona reflection integrada y la utilidad
grpcurl, que la usa.Desde mi experiencia trabajando en algunas empresas FAANG, Thrift/gRPC es realmente útil para el enrutamiento de servicios internos.
Sin embargo, buena parte de esa complejidad la gestionan los equipos que crean bibliotecas, capas de descubrimiento de servicios, enrutamiento, etc. Usar un protocolo RPC permite hacer estas cosas a una escala y velocidad que serían difíciles con un servicio JSON/REST común.
Nunca he visto una API REST en la que no se filtren verbos, y si tuviera que crear una service mesh de backend o conectar dos servicios locales mediante un stream de red, siempre elegiría gRPC.
Pero jamás usaría gRPC para algo expuesto a clientes o a la web. RPC es potente porque fija muchas decisiones e impone “una sola forma” de hacer las cosas. En cambio, si una variedad de clientes en distintos stacks tecnológicos necesita usar el servicio, REST es mucho mejor.
POST /api/doThingy.Es un RPC sencillo en el que cualquiera puede participar con el cliente HTTP más básico, y funciona bien en todos los sistemas operativos y navegadores. Tampoco hay que pelearse con si algo va en la ruta de la URL, en los parámetros de consulta o en el cuerpo.
Si usas familias de servidores que intentan hacerlo menos incómodo, como Buf o Connect, gRPC también acepta con gusto JSON sobre HTTP.
Pienso en casos como juegos en línea o MMO, donde se necesita comunicación mucho más en tiempo real que con REST, pero no sé bien si hoy en día se monta algo encima de una conexión por sockets.
También me gustaría saber qué otras cosas han intentado.
Si no vas a hacer streaming bidireccional, en general considero que gRPC es una pérdida de tiempo.
Hay un infierno de dependencias transitivas en tiempo de ejecución, un infierno de toolchain, y hasta los equipos dentro de Google que mantienen cada implementación parecen no ponerse de acuerdo filosóficamente sobre cómo deberían funcionar las capacidades básicas.
Prueba exponer una API gRPC a un equipo que no use tu lenguaje, especialmente si no es Go/Python/Java o si incluso usa versiones antiguas; o intégrala con productos comerciales listos para usar; o exponla al navegador: en todos los casos terminas necesitando una capa intermedia.
En general, gRPC fue bastante fluido.
Usar REST para comunicación entre servicios de backend tampoco tiene mucho sentido si hay requisitos de rendimiento, y salvo que sean llamadas ocasionales para recibir datos pequeños, hay pocas razones para usar un protocolo/API legible por humanos.
Si devolvías un subtipo de
oneofcuyo tipo actual no tenía campos, la conversión automática resultaba en algo como{ "id": "id", "sub_type_two": { } }.Funcionalmente servía, y si más adelante aparecía un campo, ese código seguiría funcionando. Pero en el mundo web es raro representar el tipo de respuesta con un objeto vacío, y al escribir protobuf este tipo de problemas puede no ser evidente.
Comparado con casi cualquier protocolo binario imaginable, está más bien cerca de ser anti-streaming.
Mi única experiencia usando gRPC en una empresa fue en un proyecto que otro desarrollador senior impulsó diciendo que “necesitábamos rendimiento”.
Al final también tuvimos que crear una API JSON porque el frontend debía poder consumirlo, y nadie salvo ese desarrollador tenía experiencia con gRPC. Para colmo, ese desarrollador tampoco fue mucho más allá de la guía de inicio rápido de gRPC Python y no ayudó a corregir bugs.
El proyecto fue un desastre por muchísimas razones, y nunca llegó ni cerca de una escala que justificara gRPC.
Aun así, lo poco que usé gRPC personalmente me gustó, y me dio la sensación de que requiere mucho más trabajo y reflexión. Eso quizá se deba a que he hecho muchísimas más APIs JSON.
Estoy usando ConnectRPC https://connectrpc.com/ y me está resultando interesante.
Corrige muchas de las partes problemáticas de gRPC, y espero que cuando Safari adopte WebTransport, ConnectRPC pueda desarrollar un mejor streaming.
Al principio pensé que https://buf.build era excesivo, pero la capacidad de importar archivos proto de terceros sin descargarlos uno por uno fue decisiva.
deps:- buf.build/landeed/protopatch- buf.build/googleapis/googleapisLa generación automática de SDK también es importante. Antes iba a elogiar que generaba SDK automáticamente para unos 9 lenguajes, pero en los últimos uno o dos días se actualizó y ahora veo 16 lenguajes, además de OpenAPI y otras funciones nuevas.
Yo también me dejé seducir por la falsa promesa del streaming de gRPC, y este documento encaja exactamente con mi experiencia: https://connectrpc.com/docs/go/streaming/
Gracias a eso, también se puede usar streaming bidireccional en el navegador.
Se siente como si Google hubiera hecho una guerra psicológica a toda la industria para que usara gRPC en la comunicación entre servicios internos.
La experiencia de desarrollador de gRPC es bastante peor que la de REST.
No puedes darle a alguien un simple comando para llamar a un endpoint; necesitas herramientas adicionales no estandarizadas. Además, el código del lado del cliente que se genera es un bloque feo como pocos en cualquier lenguaje.
Con un solo cambio de protocolo puedes saber estáticamente qué consumidores aguas abajo hay que actualizar y volver a desplegar, lo que puede convertir un trabajo de semanas en un cambio de una hora.
También sabes que los mensajes que aceptas y emites se validan de inmediato, y puedes almacenarlos de forma barata para restaurarlos más adelante.
Con proto obtienes documentación de API muy legible, sin que se diluya entre código o lógica de negocio. La gestión de versiones y la semántica de deprecación también vienen incorporadas, y, salvo por los mapas, admite estructuras de datos más ricas.
En comparación, JSON se ve inflado y anticuado en backend.
Anotas los tipos de datos y las firmas de funciones, obtienes algo que puedes invocar como una función real y te concentras en la lógica de negocio en vez de en boilerplate de serialización/deserialización.
Thrift también es mucho mejor que construir todo a mano, y considero que GraphQL es aún mejor.
Incluso en Go, entender la regeneración y la gestión de versiones compartidas de proto es engorroso, y empeora con cada lenguaje que se agrega.
Aun así, parece que todas las startups creen que necesitan 100 microservicios y gRPC.
La frase “si la API es una API REST, el cliente no necesita entender el formato de las URL, y ese formato no forma parte de la especificación de la API que se le entrega al cliente” está alineada con la definición de REST de Roy Fielding.
Fielding escribió que a una API REST se debería entrar sin conocimiento previo, salvo el URI inicial y un conjunto de tipos de medios estandarizados, y que, a partir de ahí, todas las transiciones de estado de la aplicación deberían ocurrir cuando el cliente elige entre las opciones provistas por el servidor.
https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypert...
Es un tema ya muy tratado, pero sigue siendo interesante que, en un sistema verdaderamente RESTful, la “especificación de API” que se le entrega al cliente debería ser solo el URI/URL del punto de entrada inicial.
Personalmente, me parece inflada y que no resuelve problemas reales.
https://en.m.wikipedia.org/wiki/HATEOAS
En particular, no sé cómo se supone que el cliente descubra los recursos manipulables o los modelos de solicitud/respuesta.
La configuración puede ser así, pero la especificación de API debería ser mucho más que una URL y describir en detalle los tipos de medios que usa el sistema. Es decir, hace falta sobre todo una descripción del cuerpo de las solicitudes/respuestas HTTP.
El enlace también dice que “una API REST debería dedicar casi todo su esfuerzo descriptivo a definir los tipos de medios usados para representar recursos e impulsar el estado de la aplicación”.
Al final, no se trata de devolver solo
application/json, sino algo específico como+json, y en la mayoría de los casos contiene datos de negocio que la aplicación debe entender, no JSON genérico.En las discusiones populares, el foco se pone solo en la URL inicial y se omite la mayor parte del trabajo de “describir los tipos de medios” del que hablaba Fielding. Por eso es natural que alguien que escucha “con una URL basta” pregunte “¿dónde está el resto de la especificación?”.
Yo también hice clic pensando que sería otro bloguero que no entiende REST, pero el autor parece conocer al menos los conceptos básicos.
También me gusta gRPC y en proyectos comerciales resulta bastante atractivo, pero para proyectos personales o idealistas creo que REST es mejor.
No me gusta usar gRPC dentro de un centro de datos.
Se elige por rendimiento, pero gRPC difícilmente puede considerarse de alto rendimiento, y la calidad de los clientes públicos es muy baja, especialmente fuera de las implementaciones núcleo en C++/Java. La implementación de Node.js, por ejemplo, es así.
No me opongo a usar protobuf como especificación de API, pero debería poder usarse junto con un protocolo de framing sobre TCP. Sin embargo, para ese estilo de RPC no hay una opción claramente dominante.
En APIs basadas en web prefiero payloads legibles, pero normalmente se usa JSON y la especificidad de tipos se vuelve laxa, lo que genera problemas de interoperabilidad entre lenguajes de backend. Especialmente en Node.js,
JSON.parsese usa como si fuera una implementación de mapeo de esquema.Para hacerlo bien, habría que generar explícitamente encoders y decoders a partir de un esquema, y entonces parte de la ventaja de usar JSON en el contexto de JS se reduce.
También estoy siguiendo el proyecto TypeSpec de Microsoft: typespec.io
Si tienes un stack tecnológico de un solo lenguaje, pierde importancia. Y si usas algo fuera de los lenguajes principales de Google, es muy probable que la experiencia no sea tan buena.
gRPC se sintió innecesariamente poco accesible para quienes estaban fuera de Google
El cliente JS de gRPC es innecesariamente pesado y bastante opaco. La idea es buena, pero la ejecución deja que desear en comparación con lo que esperan quienes están acostumbrados a la “simplicidad” de REST
RPC es semánticamente más fácil de mantener porque no obliga a encajar la cardinalidad ni las relaciones del modelo de datos en un único patrón prescriptivo. En un mundo donde las API cambian rápido, es difícil lograr entidades RESTful elegantes, y en equipos grandes con requisitos/propiedad cambiantes, un diseño centrado en servicios funciona mejor
El lado frontend no mantiene los sistemas backend. Quiere API fáciles de entender y entidades que puedan abstraerse con REST. Es el beneficiario final de ese tipo de diseño
El esfuerzo que requiere REST tiene sentido en empresas que venden API y donde los desarrolladores de terceros son clientes clave
Para el desarrollo backend, protobuf y la codificación binaria en el cable son más fáciles. Se pueden definir API y compartirlas entre servicios de forma estáticamente tipada, y también se reduce el tiempo de codificación/decodificación de mensajes. JSON no es semántico ni tipado, y además tiene mucha sobrecarga
En cambio, el frontend maneja texto y JSON de forma nativa. No quiere descargar definiciones de protobuf ni tratar datos binarios como ciudadanos de segunda, y tampoco encajan limpiamente con sus herramientas
gRPC incorpora bien enrutamiento, reintentos, canales auxiliares, streaming y semántica de descarte de protocolos, pero casi nada de eso queda expuesto al frontend. Todo está pensado para consumidores backend
Al final, es 100% una brecha de herramientas entre frontend y backend, y una falta de alineación entre la interfaz y la usabilidad
Por defecto se puede ver el código fuente, es legible para humanos y fácil de inspeccionar
gRPC está pensado para que las máquinas hablen eficientemente entre sí, y cuando interviene una persona —ya sea programando o inspeccionando solicitudes/respuestas— resulta algo incómodo
Como el contexto y los objetivos eran distintos, esta diferencia de usabilidad se entiende
A mi parecer, la implementación de buf.build es mejor
https://buf.build/blog/protobuf-es-the-protocol-buffers-type...
Parece que muchos lo eligieron porque necesitaban un protocolo tipo RPC binario con contrato, pero cuanto más te alejas de GoLang, peor se vuelve
Si es un servicio CRUD simple, REST también es suficiente