Почему Facebook это придумал? Как избежать избыточной / недостаточной выборки?

Что это?

GraphQL - это язык запросов для получения данных с сервера. Его можно в некотором роде рассматривать как альтернативу REST, SOAP или gRPC.
Создан для внутреннего использования Facebook, а позже сделан с открытым исходным кодом.
Сегодня он обслуживает сотни миллиардов вызовов API в день для Facebook и широко используется многими другими.

Почему именно GraphQL?

Итак, как мы знаем, GraphQL не является языком запросов для графовых баз данных, но это все же подходящее название, потому что он запрашивает граф данных вашего приложения.

Почему в Facebook появился GraphQL?

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

Они не думали о данных с точки зрения URL-адресов ресурсов, вторичных ключей или таблиц соединений; они думали об этом в терминах графа объектов и моделей, которые они в конечном итоге используют в своих приложениях, таких как NSObjects или JSON.

Также необходимо было написать значительный объем кода как на сервере, так и на клиенте.
Сервер должен был подготовить данные, а клиент должен был их проанализировать.

Конфликт требований к API приложения и реализации сервера может привести к серьезным проблемам с производительностью и общему плохому UX, когда мы работаем с миллиардами обращений в день.
Именно это и произошло с Facebook. .

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

Этот конфликт можно пояснить на следующем базовом примере:

Приложение Facebook запрашивает публикации, комментарии и лайки с сервера facebook.
А в ленте новостей facebook вид отдельной записи выглядит следующим образом.

Здесь мы видим, что для работы одного просмотра поста требуется более одного ресурса.
т.е. подробности публикации, автора, количество лайков, комментариев и количество репостов.
А в реальных приложениях для большинства просмотров потребуется более одного ресурса для поддержки одного просмотра.

Как выполнить этот вариант использования?

  1. Допустим, за один /posts вызов мы получаем все, что связано с сообщением. то есть получение списка лайков, комментариев вместе с каждым постом.
    Это называется избыточной выборкой.
    Но минусы этого подхода в том, что мы отправляем ненужные данные, которые не будут использоваться всегда.
    Кроме того, он приводит к большему количеству вычислений на сервере и большему потреблению полосы пропускания на клиенте, что приводит к ухудшению взаимодействия с пользователем.
  2. Иметь отдельные API для каждого типа ресурса и для каждого варианта использования.
    т.е. отдельные ресурсы для получения лайков и комментариев.
    Это называется недостаточной выборкой.
    Конечные точки, которые по умолчанию возвращают только часть данных, которые клиент на самом деле потребности требуют, чтобы клиенты совершали дополнительные вызовы для удовлетворения своих потребностей в данных, что требует дополнительных HTTP-запросов.
    Опять же, это приводит к плохому UX и дополнительным усилиям со стороны разработчиков.

Разочарование из-за вышеупомянутых ограничений вдохновило разработчиков Facebook на запуск проекта, который в конечном итоге стал GraphQL.
Используя GraphQL, они хотели переосмыслить получение данных в мобильных приложениях с точки зрения дизайнеров и разработчиков продуктов. Он перенес фокус разработки на клиентские приложения, где дизайнеры и разработчики проводят свое время и внимание.

Как Facebook решил эту проблему с помощью GraphQL

GraphQL «из коробки» предоставляет следующие функции, которые помогли Facebook преодолеть описанные выше проблемы.

1. Сильно типизирован:

Одним из очень важных свойств GraphQL является то, что он строго типизирован, то есть сервер точно знает форму каждого объекта, который может запросить клиент, и любой клиент может фактически проанализировать сервер и запросить так называемый schema.
Следовательно, ответ GraphQL возвращает данные в том же формате, в котором они были запрошены.

  • Схема GraphQL
    Она описывает форму графа данных, которую может запросить клиент. то есть какие все запросы возможны и какие поля можно вернуть.
  • Тип объекта
    type
    представляет собой тип объектов, которые можно запрашивать и получать с сервера.
  • Запрос GraphQL
    Тип запроса такой же, как и у обычного objectType, но он особенный, поскольку он является точкой входа в GraphQL API. И используя строковый запрос, клиент запрашивает данные с сервера, который в результате интерпретирует запрос, выполняет его и возвращает клиенту JSON.

Ниже приведена схема структуры типа сообщения facebook.

type Post {
    id: String!
    title: String!
    description: String
    comments: [Comment]
    likes:[Like]
}

type Comment{
    id:String
}

type Like{
    id:String
}


# The Root Query for the application
type Query {
    recentPosts(count: Int, offset: Int): [Post]!
}
# The Root Mutation for the application
type Mutation {
    writePost(title: String!, category: String) : Post!
}

2. Избегает избыточной выборки

GraphQL позволяет избежать чрезмерной выборки.
Каждый раз, когда клиент запрашивает какое-либо поле / данные, только наш сервер выполняет вычисления, необходимые для их получения.
Для указанной выше схемы используйте запрос latestPosts (count: Int, offset: Int) для получения желаемых данных.

3. Избегает недостаточной загрузки

GraphQL позволяет избежать недостаточной выборки.
Таким образом, здесь не существует ничего, что называется недостаточной / избыточной выборкой. Данные обслуживаются и вычисляются на основе запроса клиента.
Кроме того, нет необходимости открывать несколько конечных точек, чтобы получить какое-либо подмножество полей. Этой цели служит единственный запрос.

Примеры, показывающие, как GraphQL позволяет избежать избыточной и недостаточной выборки:

Здесь клиентский запрос для поля id только в сообщении и то же самое возвращается в ответе.

Здесь клиент запрашивает лайки и комментарии, и на основе запроса сервер разрешает их с помощью преобразователей для конкретных полей.

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

4. Протокол, а не хранилище :

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

5. Иерархический

Одним из важных аспектов GraphQL является его иерархическая природа. GraphQL естественно следует за отношениями между объектами, тогда как служба RESTful может потребовать нескольких сетевых вызовов или сложных операторов соединения в SQL. Такая иерархия данных хорошо сочетается с хранилищами данных с графической структурой и, в конечном итоге, с иерархическими пользовательскими интерфейсами, в которых она используется.

Вывод

Обсуждаемые выше функции, такие как строго типизированный, иерархический характер, расширяемость и т. Д. заставьте GraphQL твердо стоять напротив остальных.
Хотя предпочтение GraphQL остальным имеет и некоторые недостатки, тем не менее, GraphQL является неотъемлемой частью создания продуктов в Facebook, и его использование за пределами Facebook - это только начало.