Arquitectura de alto rendimiento graphql a sql

El motor Hasura GraphQL proporciona una interfaz de programación de aplicaciones de protocolo de transferencia de hipertexto para consultar Postgres usando GraphQL de una manera segura para los permisos.

Puede usar restricciones de clave externa en Postgres para consultar datos jerárquicos en una sola solicitud. Por ejemplo, puede ejecutar esta consulta para obtener el "álbum" y todas sus "pistas" (siempre que la tabla "pistas" tenga una clave externa a la tabla "álbum"):


Como habrás adivinado, la consulta puede atravesar la tabla a cualquier profundidad. Esta interfaz de consulta combinada con permisos permite que las aplicaciones de front-end consulten Postgres sin escribir ningún código de back-end.

La interfaz de programación de la aplicación está diseñada para ser rápida (tiempo de respuesta) y manejar un alto rendimiento (solicitudes por segundo) mientras ahorra recursos (bajo uso de CPU y memoria). Discutimos las decisiones arquitectónicas que nos permitieron lograr este objetivo.

La consulta de microservicios de datos pasa por las siguientes etapas:

  1. Resolución de sesión: la solicitud llega a la puerta de enlace, la puerta de enlace resuelve la clave de autorización (si corresponde), agrega la identificación de usuario y el encabezado de función y luego envía la solicitud al servicio de datos.
  2. Análisis de consultas: el servicio de datos recibe una solicitud, analiza el título para obtener la identificación del usuario y el rol, y analiza el asunto como GraphQL AST.
  3. Verificación de la consulta: compruebe si la consulta es semánticamente correcta y luego aplique los permisos definidos para el rol.
  4. Ejecución de la consulta: la consulta verificada se convierte en una declaración SQL y se ejecuta en Postgres.
  5. Generación de respuesta: los resultados de Postgres se procesan y se envían al cliente (la puerta de enlace agregará compresión gzip si es necesario).

Los requisitos son aproximadamente los siguientes:

  1. La pila del protocolo de transferencia de hipertexto debe agregar poca sobrecarga y debe poder manejar una gran cantidad de solicitudes simultáneas para obtener un alto rendimiento.
  2. Traducción rápida de consultas (GraphQL a SQL)
  3. La consulta SQL compilada debería ser eficiente en Postgres.
  4. Los resultados de Postgris deben enviarse de regreso de manera efectiva.

Las siguientes son varias formas de obtener los datos necesarios para las consultas GraphQL:

La ejecución de consultas GraphQL generalmente implica la ejecución de un analizador para cada campo. En la consulta de ejemplo, llamaremos a una función para obtener los álbumes lanzados en 2018, y luego, para cada uno de estos álbumes, llamaremos a una función para obtener la pista, que es un problema clásico de consulta N + 1. El número de consultas aumenta exponencialmente con la profundidad de la consulta.

La consulta ejecutada en Postgres es la siguiente:

Esta será la suma de N + 1 consultas para obtener todos los datos requeridos.

Los proyectos como Data Loader tienen como objetivo resolver el problema de las consultas N + 1 mediante consultas por lotes. El número de solicitudes ya no depende del tamaño del conjunto de resultados, sino del número de nodos en la consulta GraphQL. En este caso, la consulta de muestra requiere dos consultas a Postgres para obtener los datos requeridos.

La consulta ejecutada en Postgres es la siguiente:

Esto nos dio todos los álbumes. Para obtener todas las pistas del álbum deseado:

Esto es un total de 2 consultas. Evitamos emitir consultas para obtener la información de las pistas de cada álbum, pero usamos la cláusula where para obtener todas las pistas del álbum deseado en una sola consulta.

El cargador de datos está diseñado para funcionar en diferentes fuentes de datos y no puede aprovechar la funcionalidad de una única fuente de datos. En nuestro ejemplo, nuestra única fuente de datos es Postgres. Como todas las bases de datos relacionales, Postgres proporciona una forma de recopilar datos de varias tablas en una sola conexión de consulta. Podemos determinar las tablas necesarias para una consulta GraphQL y usar la conexión para generar una única consulta para obtener todos los datos. Por lo tanto, los datos necesarios para cualquier consulta GraphQL se pueden obtener de una sola consulta. Antes de enviarlos al cliente, estos datos deben convertirse adecuadamente.

La consulta es la siguiente:


Esto nos proporcionará los siguientes datos:

ID de álbum (_ d)

Título del álbum (_ t)

Identificador de pista

Título de la pista (_ t)

1

Albúmina 1

1

pista 1

1 Albúmina 1 2 track2
2 Albúmina m2 aire aire

Estos datos deben convertirse en una respuesta JSON con la siguiente estructura:


Descubrimos que la mayor parte del tiempo procesando la solicitud se dedica a la función de conversión (convierte el resultado de SQL en una respuesta JSON). Después de probar algunas formas de optimizar la función de conversión, decidimos eliminar esta función enviando la conversión a Postgres. Postgres 9.4 (lanzado aproximadamente cuando se lanzó el primer microservicio de datos) agregó funciones de agregación JSON, lo que nos ayudó a avanzar en la conversión a Postgres. El SQL generado será similar a:


该查询的结果将有一列和一行,并且该值被发送到客户端,无需任何进一步的转换。 从我们的基准测试来看,这种方法大约比哈斯克尔的转换函数快3-6倍。

根据查询的嵌套级别和使用的条件,生成的SQL语句可能非常大而且复杂。 通常,任何前端应用程序都有一组用不同参数重复的查询。 例如,上述查询可以针对2017年而不是2018年执行。 准备好的语句最适合这些用例。当你有复杂的SQL语句时,这些语句会随着一些参数的改变而重复。

因此,第一次执行这个GraphQL查询时:


我们准备了SQL语句,而不是直接执行它,所以生成的SQL将是(注意$1):

接下来执行这个准备好的语句:

当GraphQL查询更改为2017年时,我们只需直接执行准备好的语句:

根据GraphQL查询的复杂程度,这大致可以使我们提高10-20% .

Haskell非常适合各种原因:

  • 具有出色性能的编译语言(本)
  • 高效能的HTTP堆栈(warp,warp的体系结构)
  • 我们之前使用该语言的经验

高效能的HTTP堆栈(翘曲,翘曲的体系结构(
这是Hasura的建筑与Prisma和Postgraphile的比较。

数据库实时同步

我们之前使用该语言的经验

  1. 8GB RAM,i7笔记本电脑
  2. Postgres在同一台机器上运行
  3. wrk被用作基准测试工具,并且针对不同类型的查询,我们尝试“每秒”最大化请求
  4. 查询Hasura GraphQL引擎的单个实例
  5. 连接池大小:50
  6. 数据集:chinook

查询1:tracks_media_some


  • 每秒请求数:1375 req / s
  • 5毫秒
  • 30%
  • 30MB(Hasura)+ 90MB(Postgres)

查询2:tracks_media_all


  • 每秒请求数:410 req / s
  • 延迟时间:59毫秒
  • 查询1:轨道_媒体_部分100%
  • 每秒请求数:1375次请求/秒每秒请求数:410次请求/秒

查询3:album_tracks_genre_some


  • 每秒请求数:1029 req / s
  • 延迟时间:24ms
  • 30%
  • 30%30MB(Hasura)+ 90MB(Postgres)

查询4:album_tracks_genre_all


  • 每秒请求数:328 req / s
  • CPU:100%
  • 30MB(Hasura)+ 130MB(Postgres)

Supongo que te gusta

Origin blog.csdn.net/weixin_49470452/article/details/107506394
Recomendado
Clasificación