Header Ads Widget

Ticker

6/recent/ticker-posts

Comparación de herramientas para la unión de esquemas GraphQL: Hasura vs.Apollo

 


En el mundo de los microservicios, una API podría hacer referencia a decenas o más servicios dentro de una sola función. Desafortunadamente, esta funcionalidad significativamente elevada ha traído consigo una mayor complejidad.

Una forma de lidiar con tal complejidad es unir esquemas . La unión es un proceso sólido que vincula muchos microservicios en una sola red relacional. Esta estrategia puede ayudar a proporcionar un sistema único y poderoso que enruta las consultas correctamente.

Entonces, ¿cómo funciona la costura y qué tecnología podemos implementar para ayudar? Echemos un vistazo más profundo.

¿Qué es la costura de esquemas?

La unión de esquemas es exactamente lo que parece: unir varios esquemas para crear una única experiencia perfecta para el usuario final. En la práctica, hacer esto es un poco complicado, y es más parecido a tomar una masa de cuadrados, círculos y triángulos y combinarlos en una forma singular y comprensible: cada subcomponente aún debe existir como una estructura estable con la misma integridad en combinación como en un ser singular, al tiempo que facilita la comunicación con una única entidad externa.

En términos de API, lo que esto significa esencialmente es tomar una gran cantidad de API, definir estas relaciones internas, puntos finales de esquema y relaciones generalizadas, y luego formar una capa de proxy para traducir estas solicitudes. Las solicitudes de los usuarios finales se realizan normalmente a través de una API maestra, que sirve como un ómnibus de esquemas.

¿Por qué coser en absoluto?

La unión es una solución a un problema central del modelo de microservicio. Si bien los microservicios cuentan con muchos aspectos positivos, su complejidad puede ser un problema importante .

Cada módulo adicional aumenta la necesidad de comprender el flujo de tráfico, el manejo de datos implícito y el método relativo por el cual se consultan los datos. Han surgido muchas soluciones para simplificar esta arquitectura, y la unión es simplemente una evolución, lo que permite realizar consultas sin problemas.

Stitching ofrece lo mejor de dos mundos: le permite hacer referencia a muchos microservicios mientras actúa como una API singular. Esto significa que nuestra oferta es menos confusa, más eficaz y, en última instancia, proporciona una mejor experiencia de usuario.

Los 4 pasos de la costura

El objetivo final de este proceso es tener un flujo de trabajo muy específico : el cliente realiza una solicitud a una API de Maser, que luego se envía a una capa de traducción proxy. En esta capa, la solicitud se divide en varias API diferentes, y cada una responde a la solicitud con la parte de los datos de la que son responsables. A continuación, estas respuestas se combinan juntas, nuevamente en la capa de proxy. Esta respuesta combinada se envía al cliente a través de la salida de la API maestra.

1. Introspección de la API

Para hacer esto, hay cuatro pasos básicos . Primero, debemos realizar una introspección de la API . Este proceso implica observar las numerosas API que se ofrecen actualmente, la forma en que se manejan nuestros datos y el flujo general de datos dentro de nuestro ecosistema de API. En efecto, estamos aprendiendo con qué herramientas y datos tenemos que manipular, ya que ni siquiera podemos comenzar a considerar cómo se verá el resultado final hasta que descubramos cuál es nuestro estado actual.

2. Cambiar el nombre de la API

A continuación, debemos cambiar el nombre de la API . En esta etapa, buscamos mitigar las colisiones entre las distintas API internas, específicamente para evitar que dos productos de desarrollo con nombres diferentes entren en conflicto. En la mayoría de los casos, la última API gana en colisiones de nombres, pero eso no es lo que queremos: queremos que cada API pueda funcionar internamente y queremos evitar colisiones, tanto en llamadas, llamadas a funciones internas, convenciones de nombres y generalmente como un punto de integridad de los datos.

3. Conecte los campos

Ahora queremos abordar el tercer paso de este proceso, que es Conectar los campos . Ahora que entendemos nuestras API y nos hemos asegurado de que las colisiones se manejen internamente, debemos definir qué campos se conectan específicamente a otros campos y tipos de datos. Dado que esencialmente estamos combinando una gran cantidad de llamadas en una llamada de cliente singular, necesitamos saber dónde se conecta cada ruta de datos, cómo se conecta y cuál es la salida esperada. Al hacer esto, podemos comenzar a enrutar estas llamadas dependiendo de su función y tipo, facilitando así la totalidad de la conversación interna que se produce cuando se realiza una solicitud de cliente.

4. Resuelva los tipos

Finalmente, queremos resolver los tipos . Aquí, vamos a tomar todo lo que hemos aprendido, todas las medidas de mitigación que hemos implementado y las conexiones de campo más grandes que hemos realizado, y especificaremos qué esquema maneja qué datos y cómo estos datos se resuelven realmente internamente. entre diferentes puntos finales. Si bien esto se puede hacer de una amplia variedad de formas, el resultado final es un sistema que resuelve claramente las solicitudes de datos a los sistemas apropiados y que combina las salidas de cada API interna individual en una salida apropiada para el consumo externo.

Caveat Emptor

Este proceso es muy eficaz, pero tiene algunas advertencias importantes que deben tenerse en cuenta. Tenga en cuenta que no todas estas advertencias se aplican a cada situación, como con cualquier implementación de API, la arquitectura, el esquema y la implementación específicos del código base dictarán el éxito o el fracaso, por lo que una advertencia o declaración de carta blanca nunca cubrirá cada caso. Dicho esto, estas advertencias son generalmente aplicables a la mayoría de las soluciones cuando se trata de API Stitching.

Pros

Hay algunas ventajas importantes de este enfoque: la suma total de estos puede denominarse "eficiencia". Éstas incluyen:

  • Una API para gobernarlos a todos: dado que hay una única API que orquesta todas las conversaciones internas que ocurren, no necesita orquestar los viajes de ida y vuelta que de otro modo serían necesarios para reflejar la misma funcionalidad en una API sin coser.
  • Una API para descubrirlo todo: en un entorno típico, la introspección de API requeriría una consulta de introspección para cada proceso y API involucrados, lo que llevaría mucho tiempo y tendría que combinarse manualmente. Con el método cosido, una única consulta de introspección en el nivel superior del cliente expondrá todos los datos disponibles a través de microservicios a través de su interfaz cosida.
  • Reducción de superficie: visualmente, su API parece tener una superficie de ataque más pequeña ya que solo hay un punto final expuesto al cliente. La inversa, en la que varios microservicios tendrían varios puntos finales expuestos, da la apariencia de una mayor superficie de ataque.

Contras

También hay algunas desventajas importantes en este enfoque, que se pueden resumir como "puntos de falla":

  • Una API para bloquearlos a todos: debido a que tiene un único punto final, si ese punto final deja de funcionar, "se acabó el juego". Un solo punto de falla para el cliente externo puede ser un gran problema en ciertas aplicaciones y debe mitigarse independientemente de si se adopta o no la unión.
  • No siempre es una gran idea: la unión es una excelente implementación para muchos casos de uso, pero en otros, está lejos de ser ideal. Proporcionar una única fuente de contenido de verdad almacenado en caché no es un gran entorno para la unión, y la realidad de la unión en sí misma, que introduce complejidad en lo que de otro modo podría ser un sistema relativamente simple, son argumentos sólidos en contra del enfoque.
  • Solo porque puedes: la realidad es que, solo porque puedes hacer algo, no significa que debas hacerlo. Ha habido muchos casos en que se ha adoptado una tecnología sólida como estándar de jure, y la unión entra en gran medida en esta línea de pensamiento: no todas las colecciones de microservicios deben tener su esquema unido y, en algunos casos, esto es simplemente complejidad por la complejidad.
  • Requisitos de proxy: este enfoque requiere un proxy, y no todos los entornos, estándares o requisitos pueden admitirlo. Si bien GraphQL y otras arquitecturas sugieren proxies como una mejor práctica en muchos casos, hay ciertas situaciones en las que un proxy es una elección absolutamente pobre y puede causar más problemas de los que soluciona.

Casos de uso

Como ejemplo de por qué esta unión puede ser una buena idea, veamos un posible caso de uso. En esencia, los esquemas de API de unión le permiten presentar una experiencia unificada a su usuario sin tener que realizar una multitud de llamadas de ida y vuelta claramente externas o complicadas. Este tipo de costura, entonces, es perfecto para eventos y es altamente efectivo en eventos localizados específicamente.

Supongamos que está organizando algún tipo de evento para profesionales de API en Suecia. Como organizador principal, ha creado una aplicación para teléfonos inteligentes que aprovecha una API integrada para proporcionar una amplia variedad de información. Gracias a la unión, puede tener una experiencia unificada que permanece dentro de la aplicación en todo momento, entregando datos sin problemas mientras solo expone un punto final central. Su API cosida puede:

  • Llame a una API de reservas para buscar vacantes locales, agilice los procesos de registro para hoteles asociados e informe sobre la utilización de hoteles asociados para justificar la inversión comercial en eventos futuros;
  • Llame a una API meteorológica para proporcionar información sobre las condiciones ambientales en todo momento, tal vez incluso cotejando, comparando y contrastando diferentes fuentes de información para proporcionar una condición meteorológica estimada más precisa;
  • Organice una variedad de API de microservicio que se utilizan para la gestión de pases, el registro de exposiciones y el aprovisionamiento de talleres para los invitados que asisten a pistas de desarrollo específicas en sus seminarios;
  • Proporcione varios puntos finales de tolerancia y de respaldo para detectar llamadas de API deficientes, llamadas interrumpidas o puntos finales críticos que necesiten redundancia (como llamar a varios puntos finales para programar sistemas para garantizar que todos los programas estén actualizados y sean precisos).

La conclusión es que con una API unida, puede realizar un montón de funciones con muy poca diafonía obvia, aprovechando una multitud de API a través de un solo punto final. Puedes hacer más con menos.

Opciones de costura

Ahora que hemos analizado la costura en un sentido general, echemos un vistazo breve a dos proveedores específicos en el espacio: Hasura y Apollo.

Hasura y Apollo: una breve descripción

Hasura y Apollo se ocupan de la costura en general de la misma manera, lo que sirve como un gran ejemplo de cómo podría verse realmente este proceso.

Hasura

Bajo Hasura, todas las API externas se consideran "esquema remoto"; como tal, el primer paso para utilizar Hasura es que usted cree una instancia GraphQL personalizada que incluye resolutores específicos para cada esquema remoto.

Una vez que estos recursos remotos reciben un nombre y se agregan a un punto final de la URL del servidor, Hasura puede resolver cada solicitud a cada recurso a través de la interfaz singular, tomando una solicitud para una función específica y enviándola en su lugar al esquema remoto, pero tratando la salida de datos devuelta. como si todavía fuera parte de la solución API singular.

Hasura requiere que todos los nombres de campo de nivel superior sean únicos y utilicen una coincidencia que distinga entre mayúsculas y minúsculas para evitar colisiones. Esto también permite fusionar tipos con el mismo nombre exacto, en lugar de tratarlos como entidades separadas, lo que puede permitir una mayor claridad a través del diseño.

En este momento, sin embargo, Hasura tiene algunas limitaciones. No se pueden usar diferentes nodos GraphQL juntos en la misma consulta; todos los campos deben ser del mismo servidor para que funcionen correctamente. Además, Hasura no admite métodos de suscripción para esquemas remotos, lo que elimina algunas posibilidades en la fase de diseño.

Los esquemas remotos se manejan a través de una GUI del lado de Hasura, que se ve de la siguiente manera. El uso de una GUI es importante aquí y constituye una fuerte propuesta de valor para esta solución para los desarrolladores que favorecen tales implementaciones.

Apolo

Apollo funciona de manera muy similar, pero en su lugar usa "mergeSchemas" como un método con nombre para combinar los esquemas. Al cambiar de esta manera, Apollo puede admitir esquemas remotos o locales, expandiendo las posibles permutaciones de esquemas en gran medida. Los esquemas remotos se combinan mediante un proxy local que llama al extremo remoto, que luego devuelve el esquema para los procesos de combinación locales.

Apollo también maneja la escritura de una manera interesante. Apollo permite campos personalizados que extienden los tipos existentes para traducir entre tipos de contenido; en su instancia de documentación, esto permite al usuario cerrar la brecha entre el contenido y su autor en una sola consulta, utilizando un campo personalizado para transmitir esta información sin crear contextos peticiones.

Además, Apollo también admite transformaciones para cambiar estos esquemas antes de fusionarse, lo que permite un mayor control sobre lo que se fusiona y con qué propósito. Las transformaciones permiten la delegación de nuevos campos, la traducción entre tipos y nombres de campos nuevos y antiguos, y más procesos complejos para controlar y personalizar completamente la salida del esquema combinado.

Según la documentación de Apollo, un ejemplo de costura completo se ve como sigue.

const mergedSchema = mergeSchemas({
schemas: [
chirpSchema,
authorSchema,
linkTypeDefs,
],
resolvers: {
User: {
chirps: {
fragment: `... on User { id }`,
resolve(user, args, context, info) {
return info.mergeInfo.delegateToSchema({
schema: chirpSchema,
operation: 'query',
fieldName: 'chirpsByAuthorId',
args: {
authorId: user.id,
},
context,
info,
});
},
},
},
Chirp: {
author: {
fragment: `... on Chirp { authorId }`,
resolve(chirp, args, context, info) {
return info.mergeInfo.delegateToSchema({
schema: authorSchema,
operation: 'query',
fieldName: 'userById',
args: {
id: chirp.authorId,
},
context,
info,
});
},
},
},
},
});

Conclusión

La unión de esquemas es una excelente manera de eliminar la complejidad innecesaria al tiempo que obtiene los beneficios de un diseño arquitectónico de microservicio subyacente complejo. Si bien tiene sus propias advertencias, como con cualquier implementación, este proceso ofrece la promesa de un diseño de microservicio efectivo: mayor flexibilidad, diseño segmentado, pero con una experiencia de usuario única.

¿Qué opinas sobre la costura de esquemas? ¿Cuáles son sus pensamientos sobre Hasura y Apollo? ¿Tiene alguna alternativa preferida? Háganos saber en los comentarios a continuación.

Publicar un comentario

0 Comentarios