Рекомендации по использованию GraphQL

Что такое GraphQL?

GraphQL — это язык запросов для API и среда выполнения для выполнения этих запросов с использованием существующих данных. GraphQL предоставляет полное и понятное описание данных в вашем API. Это дает клиентам возможность просить именно то, что им нужно. Ничто больше не облегчит с течением времени развитие API и не предоставит мощные инструменты разработчика.

Но когда мы говорим о графе QL, часто имеется в виду набор логики для построения и анализа запросов.

Преимущество заключается в том, что клиентская сторона может определить, какие поля им нужны, а сервер возвращает только это.

решить проблему с избыточной и недостаточной загрузкой

  • Чрезмерная загрузка — это когда клиент загружает больше информации, чем действительно нужно приложению.
  • Неполная выборка — это когда конечная точка не предоставляет всю необходимую информацию, поэтому клиенту приходится делать несколько запросов, чтобы получить все, что нужно приложению.

Пример

https://github.com/iamshaunjp/graphql-playlist/blob/lesson-36/server/schema/schema.js
Определите тип, определите запрос, мутации и преобразователи.

Вы можете получить только то, что уже определено в схеме, но у вас есть возможность получить или обновить любое подмножество определенных полей. Это GraphQL, который внутренне обрабатывает логику подполей.

Где оно живет??

Есть пара вариантов использования

https://www.howtographql.com/basics/3-big-picture/

Проще говоря, вы помещаете на сервер дополнительную логику для фильтрации и обновления выбранных полей.

Протокол

GraphQL не зависит от протокола прикладного уровня. Вы можете использовать HTTP/S или даже веб-сокет.

Чаще всего он работает через HTTP, но, естественно, через TCP для надежной передачи данных.

Если вы используете библиотеку Spring, вы можете бесплатно настроить:



Отдых против GraphQL

Конечная точка

REST: сервер определяет количество фиксированных конечных точек для ресурсов, и клиенты должны делать отдельные запросы к разным конечным точкам для получения данных.

ГрафQL:

GraphQL имеет только одну конечную точку и позволяет клиентам делать определенные запросы для получения того, что им нужно.

Сложнее указать ограничение скорости API.

Кэширование

REST: API-интерфейсы REST могут использовать механизмы кэширования HTTP.
Кэширование приложений (веб-браузеры, max-age=3600, запросы GET), а не кэш на стороне сервера

GraphQL: невозможно создать HTTP-кеш только с одной конечной точкой

Производительность

GraphQL: Разбор запросов GraphQL и вычисление плана выполнения запроса — это задачи, требующие интенсивного использования памяти и процессора, которые будут меняться в зависимости от размера запроса.

Метод запроса

REST использует предопределенные методы HTTP (GET, POST, PUT, DELETE).

GraphQL при запуске через HTTP использует одну конечную точку POST.

Структура ответа

ОТДЫХ: ответы имеют фиксированную структуру, предопределенную в серверной части.

GraphQL: ответы имеют ту структуру, которую запрашивает клиент.

Количество запросов

ОТДЫХ: Клиентам может потребоваться выполнить несколько запросов к разным конечным точкам, чтобы собрать все необходимые данные.

GraphQL: клиенты могут получать все необходимые данные за один запрос, сокращая количество сетевых обращений.

Документация

ОТДЫХ: напишите свои собственные инструменты OpenAPI/Swagger.

GraphQL: схема уже является документом (функция самоанализа/GraphiQL/другие инструменты визуализации)

REST хорошо известен, и его легко начать.
REST способствует четким границам ресурсов и использует стандартные методы HTTP (GET, POST, PUT, DELETE) для выполнения CRUD-операций над ресурсами. Это может сделать API более предсказуемым и простым для понимания.
Отлично подходит для производительности с точки зрения использования HTTP-кэша.

GraphQL обеспечивает гибкость запроса данных при работе со сложными типами данных.
Отлично подходит для производительности с точки зрения сокращения количества вызовов, уменьшения размера запроса/ответа
Во многих случаях интерфейс может просто отредактируйте запрос, чтобы сделать что-то новое, серверной части не нужно создавать новый API (пока преобразователи все еще работают)

Часто вам нужен только один архитектурный стиль. Но даже если у вас есть код для обоих, они тоже не конфликтуют. Таким образом, ваши клиенты могут использовать тот вариант, который им больше подходит.

Как работает GraphQL

Все кажется волшебным, что вы просто указываете в запросе, что вы хотите, и каким-то образом он знает, как получить данные, и автоматически знает, что обновлять?

резольверы. Мы можем рассматривать преобразователи как простые функции, которые возвращают данные для определенного открытого поля GraphQL. https://graphql.org/learn/execution/

Каждое поле каждого типа поддерживается функцией resolver, предоставляемой разработчиком сервера GraphQL. Когда поле выполняется, вызывается соответствующий резольвер для получения следующего значения.

Разрешение на уровне поля

Стоит отметить, что сервер GraphQL имеет встроенные преобразователи по умолчанию, поэтому вам не нужно указывать функцию преобразователя для каждого поля.



Проблема N+1 в GraphQL

любой тип связей один ко многим: 1 сценарий и множество сценариев зданий
Требуется 1 вызов для получения сценария и N вызовов для получения соответствующего сценария здания
См. пример
Почему это важно? Как клиент вы можете легко запросить данные, которые выполнят гораздо больше запросов к базе данных, чем вы ожидаете.
Если вы не исправите это, это приведет к огромной проблеме с производительностью.

Решение — загрузчик данных.

пакетная обработка и кэш



Обеспокоенность

Нам следует перейти к GraphQL, зная о проблеме.

Ограничение скорости

Проблема в том, что при наличии одной конечной точки сложно объединить различные варианты использования API.

Одним из решений является определение сервером «стоимости» или «сложности». И сравните до и после запроса.

Вот как это делает github:

https://docs.github.com/en/graphql/overview/resource-limitations#rate-limit

Определенно это работа.

Безопасность — вредоносные запросы

В сообществе GraphQL большое внимание уделяется злоупотреблению глубиной запросов. Вы увидите, что это только один из способов создания потенциально вредоносных запросов, но в любом случае об этом стоит упомянуть, поскольку это популярная проблема.

query {
  store {
    product {
      store {
        product {
          ... and so on
        }
      }
    }
  }
}

Хотя это может выглядеть очень плохо, глубина запроса не обязательно хуже ширины запроса:

query {
  a: product { name }
  b: product { name }   
  c: product { name }
  d: product { name } 
  ... and so on
}
  • Использование шаблона загрузчика данных/кэширования данных, чтобы повторяющиеся поля или рекурсивные поля имели кэшированные результаты.
  • Использование сложности запроса, как мы рассмотрели выше.Мы хотим использовать сложность запроса, чтобы блокировать определенные запросы до того, как они будут выполнены, а также использовать ее в качестве механизма ограничения скорости.
  • Многие библиотеки GraphQL имеют настройку максимальной глубины запроса, которую вы можете использовать для ограничения глубины. Это здорово, только не путайте это с способом остановить все дорогостоящие запросы. Это только одна модель доступа.

Безопасность — аутентификация и авторизация

Поскольку GraphQL можно использовать с HTTP/S, мы все равно можем передать токен носителя авторизации в заголовке. Даже если вы используете webSocket, он изначально устанавливает соединение через HTTP/S, поэтому токен носителя все еще существует.

Авторизация будет непростой. Если у вас есть только один API, как убедиться, что определенный пользователь имеет доступ к одному ресурсу, но не к другому?

Масштабируемость

Масштабируемость — это способность системы повышать производительность в ответ на увеличение требований к обработке приложений и системы.

Проблема масштабируемости возникает, когда система получает слишком много запросов. Неважно, в какой форме находится запрос — в REST или GraphQL. Таким образом, худшая проблема с масштабируемостью возникает не потому, что вы используете одну архитектуру API.

Перечисление некоторых распространенных стратегий масштабирования, которые могут применяться как к API REST, так и к API GraphQL.

Базы данных часто являются самым большим узким местом

  • оптимизировать запросы к БД
  • Денормализация и предварительная агрегация (денормализация — это метод объединения данных в одну таблицу для ускорения поиска данных)
  • Горизонтальное секционирование (разбиение большой базы данных на множество меньших баз данных)
  • Пул соединений с БД
  • ограничение скорости
  • Кэширование приложения/браузера
  • Разбиение на страницы (как заставить серверную часть поддерживать гибкие запросы?)
  • уменьшить размер запроса и ответа
  • Автоматическое масштабирование и балансировка нагрузки
  • Асинхронная обработка
  • Сети доставки контента (CDN)
  • масштабирование предполагает увеличение ресурсов (ЦП, памяти, хранилища) отдельного сервера.
  • масштабирование предполагает добавление в систему дополнительных экземпляров серверов или узлов для удовлетворения возросшего спроса.

Как протестировать?

Разница здесь в том, что у REST API есть несколько конечных точек для тестирования, но в GraphQL у вас есть только одна. Так как же протестировать всю свою логику через эту единую конечную точку?

Использовать зависимость тестера

https://docs.spring.io/spring-graphql/docs/current/reference/html/#testing.graphqltester

Следуйте примеру

https://www.youtube.com/watch?v=0b0x3C_BTT8

Проблема здесь в том, что тест фактически отправляет запросы к базе данных.

Каким-то образом внедрить источник тестовых данных

Выполнение

зависимости

определить схему

создавать серверные преобразователи

настроить тестовые примеры