Горизонтальное масштабирование и GraphQL в среде Node.js - PullRequest
0 голосов
/ 02 мая 2018

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

В статье Я прочитал, что можно создавать приложения в реальном времени, используя GraphQL с «подписками», и в дополнение к этому, он прост в использовании protocole и имеет преимущество в виде минимизации туда и обратно. поиск объектов и, следовательно, использование меньшего количества ресурсов.

Но что, если нам нужно добавить новый сервер / узел в систему для горизонтального масштабирования? Возможно ли это с помощью GraphQL?

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

1 Ответ

0 голосов
/ 03 мая 2018

В скором времени - да. Мы сделали это, и это работает довольно хорошо.

Хитрость в том, что вы должны думать глубже, чем просто рабочие приложения API, когда дело доходит до горизонтального масштабирования. Если вам нужна push-архитектура , она должна быть асинхронной с самого начала.

Для этого мы использовали системы массового обслуживания , а именно RabbitMQ .

Представьте себе такой сценарий создания отчета, который может занять до 10 минут:

  1. Клиент подключается к нашему API GraphQL (экземпляр 1) через WebSocket
  2. Клиент отправляет команду на создание отчета через WebSocket
  3. API создает токен для команды и помещает команду для генерации отчета в CommandQueue (в RabbitMQ), возвращая токен Клиенту.
  4. Клиент подписывается на события результата своей команды, используя токен
  5. Какой-то бэкэнд-работник берет команду и выполняет процедуру генерации отчета
  6. В течение этого времени API GraphQL (экземпляр 1) умирает
  7. Клиент автоматически переподключается к GraphQL API (экземпляр 2)
  8. Клиент продлевает подписку с ранее приобретенным токеном
  9. Работник завершен, результаты в EventsQueue (RabbitMQ)
  10. ВСЕ наши экземпляры GraphQL получают информацию о ReportGenerationDoneEvent и проверяют, слушает ли кто-нибудь его токен.
  11. GraphQL API (экземпляр 2) видит, что Клиент ожидает результатов. Подталкивает результаты через веб-сокеты.
  12. API GraphQL (экземпляры 3-100) игнорируют ReportGenerationDoneEvent.

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

И что в этом хорошего, вы получаете хорошее горизонтальное масштабирование, повторяемость событий (повторные попытки), разделение проблем (клиент, API, рабочие), как можно быстрее отправляете данные клиенту и по мере того, как вы упомянул, что вы не тратите пропускную способность на are we done yet? запросов.

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

Хорошие мысли о SocketCluster. Это оптимизировало бы шаг 10 в вышеприведенном сценарии, но на данный момент мы не видим никаких проблем с производительностью при широковещательной рассылке ReportGenerationDoneEvent всему кластеру API. При наличии большего количества экземпляров или многорегиональной архитектуры это будет необходимо, так как это позволит улучшить масштабирование и разделение.

Важно понимать, что SocketCluster работает на уровне связи (WebSockets), но уровень логического API (GraphQL) выше этого уровня. Чтобы сделать подписку GraphQL, вам просто нужно использовать протокол связи, который позволяет передавать информацию пользователю, а WebSockets позволяет это.

Я думаю, что использование SocketCluster - хороший выбор дизайна, но не забывайте перебирать реализацию. Используйте SocketCluster только тогда, когда вы планируете открыть много сокетов в любой момент времени. Кроме того, вы должны подписываться только тогда, когда это необходимо, поскольку WebSocket имеет состояние и требует управления и пульса.

Если вас больше интересует асинхронная архитектура бэкэнда, которую я использовал выше, ознакомьтесь с шаблонами CQRS и Event Sourcing.

...