Записки программиста #2, GraphQL

В этой записке расскажу немного о GraphQL и с тем как я его на Spring накручивал и небольшой опыт о попытке реализовать ApiGateway.

Для тех кто не вкурсе, расскажу немного. GraphQL это альтернатива RestFul, отличие в том, что в GraphQL есть только один endpoint, который принимает запросы на специальном языке, разбирает запрос на АСТ токены и вызывает различные резолверы на сервере для загрузки данных. В отличии от REST, GraphQL позволяет выбирать самостоятельно данные которые клиентское приложение захочет получить. Например у нас есть такая модель

{
"id": 1,
"title": "Записки программиста #2, GraphQL",
"rating": 4.4
"author": {
"id": 2,
"name": "Вячеслав Гуссер"
}
}

Это представление поста которое отдается по rest api, если мы сделаем запрос на API, то мы получим такую модель, можно извратиться и сделать API гибким на получение различных моделей, но это не очень. Альтернатива - GraphQL, допустим мне надо получить только название статьи, без рейтинга и от автора только имя, тогда мы напишем такой GraphQL запрос:

query {
post(id: 1) {
title
author {
name
}
}
}

Этот запрос выполнит метод post(long id), на бекенде и из вернувшейся модели сформирует нам ответ с данными которые мы захотели на клиенте (это так если не вдаваться в подробности). Красивый подход, вроде даже удобно, нет ругани с фронтенд разработчками по моделями. И так как этот QL можно использовать по http, то мы получаем масштабируемое решение. Но есть одно НО, нам надо описывать схемы и типы данных, а это приводит к проблемам в распределенной системе.

Про установку на spring.

Я столкнулся с рядом проблем.

  1. При установке ранних версий, например 4.3 - 4.4, мы получаем GraphQLServlet который работает через MultipartData, на который клиент не может послать нормально запрос, соответственно еще и интерфейс GraphiQL для выполнения запросов тестирования тоже не работает
  2. Не понятные сообщения об ошибках, которые я смог понять только продебажив код.
  3. Не приятные ограничения GraphQL, у вас не может быть бекенда на котором нет хотя бы одного запроса, у вас не может быть бекенда который состоит только из операций мутации

Первая проблема решается просто выбором версии, если Вы используете Spring Boot 2.0.+, то просто ставьте последнюю версию стартера и все будет ок.

Вторая проблема вытекла у меня из третьей, я написал такую схему:

schema {
query: Query
mutation: Mutation
}

type Query {

}

type Mutation {
createCallback(request: Callback): Status
}

input Callback {
//
}

type Status {
//
}

И я получал NullPointerException с непонятной ошибкой, вот как Вы думаете? Может ли быть бекенд без запросов на чтение? Отвечу за Вас, конечно может! Но GraphQL так не думает, ошибка была в том, что тип Query у меня был пустым и мне пришлось писать что-то такое

schema {
query: Query
mutation: Mutation
}

type Query {
_: Boolean
}

type Mutation {
createCallback(request: Callback): Status
}

input Callback {
//
}

type Status {
//
}

Тогда у меня все завелось. Потом я уже увидел на github и еще позже в спеке, что пустых типов в GraphQL быть не может и то что Query обязательный. P.S решение третьей проблемы так же выше.

Проблема N+1, для коллекций с сущностями и связями там побороли с помощью @Batch резолверов, об этом можно не переживать.

Ну и последнее о чем я хотел бы сказать. Это динамический ApiGateway в микросервисной архитектуре для пачки микросервисов. Мне хотелось написать следующий Gateway для своих сервисов:

  1. Чтобы я мог легко добавлять новые микросервисы и их эндпоинты в gateway
  2. Чтобы я мог применять различные фильтры (например авторизацию) для определенных сервисов или эндпоинтов
  3. Чтобы я мог писать код который сможет изменять ответы от сервисов так как мне нужно.

GraphQL классно решает последнюю проблему, и я хотел сделать это именно на graphql. Но как только я попытался, то встала проблема. Если я буду использовать GraphQL, то он будет сильно конфликтовать с первым требованием.

Я не смогу легко добавлять новые сервисы и эндпоинты и вот почему.

  1. Мне надо расширить схему
  2. Мне надо добавить новые типы
  3. Мне надо добавить реализацию этих типо в Java коде

Это не то что я хотел. По-этому я сделал иначе.

Решить эту проблему можно, но у меня не было достаточно времени на правильное решение данной проблемы.

В итоге:

GraphQL - классная технология, ее можно использовать в новых сервисах, но интегрировать ее как ApiGateway не так просто, если Вам конечно не все равно на свое время

 

Java
06.08.2018
1 ответ
авторизуйтесь чтобы ответить