Архитектура Стартапа - Anton Skogorev Engineering & AI – Telegram
Архитектура Стартапа - Anton Skogorev Engineering & AI
2.1K subscribers
49 photos
1 video
2 files
109 links
Канал про архитектуру быстрорастущего бизнеса.

Привет, меня зовут Антон @skogorev.
Я - Технический Директор AI Center Tinkoff, ex Yandex Go Senior EM.

В переписках остается много полезных материалов, теперь я собираю их на этом канале.
Download Telegram
Microservices: don’t use them yet!
Микросервисы: пока не используйте их!

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

— Количество микросервисов должно быть меньше, чем количество разработчиков
— Методы сервиса теперь обязательно должны иметь REST api и валидации
— Переключения контекста реально дороги
— Монорепозиторий - серебряная пуля

https://medium.com/teamzerolabs/micro-services-dont-use-them-yet-f58a2758d8f9

#monolith #microservices #practices #en
Шардирование по географии - скорее всего, плохое решение для вас.

Достигая какой-то критической массы нагрузки своего сервиса, вы приходите к шардированию - осмысленному разделению обработки данных (для примера, клиентских запросов) по несвязанным кластерам.

Одна из самых простых вещей, которая приходит в голову - это разделить пользователей по географии, например, по городам: пользователи из города N будут всегда обрабатываться на кластере 1, пользователи из города M будут всегда будут приходить на кластер 2.

Но за простотой реализации такого подхода стоит достаточно сложная оркестрация (и, даже, жонглирование) нагрузки. У вас есть 2 кластера: на одном отправляются запросы из города N, на другой - из города M, нужно держать в голове:
— В какой кластер добавлять запросы из третьего нового города
— Что делать, если границы города N сильно меняются и этот кластер уже не выдерживает
— Как перераспределять ресурсы, если какой-то город выключается

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

По теме шардирования, можно почитать неплохой доклад с конференции HighLoad:
https://habr.com/en/company/oleg-bunin/blog/433370/
Event Sourcing
https://martinfowler.com/eaaDev/EventSourcing.html

Долго думал как подступиться к этой обширной теме. Сама идея кажется просто замечательной — вместо того, чтобы в stateful сервисе безвозвратно менять этот самый state (например, апдейтом в базу данных), можно вести event-log изменений. Этот лог изменений можно будет накатывать на ту же базу данных и иметь ее последнюю версию, можно полностью восстановить текущее состояние с нуля, можно получить снапшот на абсолютно любой момент времени в прошлом, можно даже сделать rollout (из предположения, что у эвента будет тривиальная обратная операция). Из практических целей стоит отдельно отметить возможность ретрансляции эвентов в другие системы, например, аналитические без каких-то специальных телодвижений.

Помимо очевидных плюсов, тако подход встречается в паре с CQRS, где подобный event-log будет единым источником правды.

Но самое интересное, это, конечно, минусы. В "каноническом описании" по ссылке ниже все очень подробно расписано, я лишь остановлюсь на некоторых:
— Дороговизна. Если эвентов очень много, нужно искать трейдофы на хранение, восстановление, сохранение снапшотов.
— Усложнение кода. Получить результат из системы с event-sourcing может быть сложной задачей.
— Интеграция с сервисами, не живущие в такой же идеологии (тут рекомендуют писать обертки для таких сервисов, что тоже своего рода усложнение).

Делитесь своими комментариями, ссылками и успешными примерами использования в чате.

https://martinfowler.com/eaaDev/EventSourcing.html
https://microservices.io/patterns/data/event-sourcing.html

#pattern #microservices #practices #doc #en
Plug-in Architecture

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

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

Здесь ядро — основная функциональность вашего приложения, предоставляющая интерфейсы для расширения с помощью концепции плагинов.
Плагины — расширения, которые by design не оказывают влияние на другие плагины, не могут повредить ядро, так как оказывают влияние через безопасные интерфейсы.

Вся концепция предоставляет ряд преимуществ:
— расширяемость — концепция позволяет достаточно легко подключать новую функциональность через плагины.
— безопасность — если считать, что каждый плагин можно легко отстрелить, если он по какой-то причине не работает, то модификация плагинов не будет влиять на основную функциональность приложения.
— изолированность — плагины изолированы друг от друга и связаны с ядром через определенный интерфейс, что предотвращает губительные зависимости.

https://medium.com/omarelgabrys-blog/plug-in-architecture-dec207291800

#practices #medium #article #en
Все, что можно сделать на бэкенде — нужно делать на бэкенде

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

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

Давайте возьмем противоположную позицию — бэкенд все знает про клиент и отвечает за всю визуализацию. Он присылает на клиент детальную информацию об экранах, текстах, кнопках — да вообще по-максимуму. Прямо из коробки это дает возможность быстрого изменения клиентов, нивелируя весь лаг деплоя приложения в сторы. Можно проводить А/Б тестирования, даже на лету менять часть какой-то функциональности, если это позволяет ваше АПИ.

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

В сегодняшней заметке ссылка на видео Highload++ 2017 по теме
https://www.youtube.com/watch?v=G-AiDkZLOIs

#practices #backend #client #video #highload #youtube #ru
Code review checklist for distributed systems
https://medium.com/swlh/code-review-checklist-for-distributed-systems-b3fb94be5bfa

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

При межсервисных запросах:

Что делать, когда запросы во внешний сервис возвращают ошибку?
— иметь ветвь обработки ошибки
— иметь сценарии восстановления после ошибки
Что делать, когда внешний сервис недоступен?
— всегда ставить таймауты на запросы
— делать какое-то явно определенное число перезапросов
— использовать circuit breaker
— не обрабатывать таймауты как ошибки

При построении сервиса, который другие сервисы будут использовать:

— все интерфейсы API должны быть идемпотентными
— явно определить времена ответа и пропускную способность
— определить и лимитировать батчевые запросы
— думать о мониторингах сервисов без потребности смотреть внутрь самих сервисов

Общие рекомендации:

— более агрессивно кэшировать
— определить единицу сбоя при ошибках
— инкапсулировать внутренние структуры сервисов и не размазывать их по системе

https://medium.com/swlh/code-review-checklist-for-distributed-systems-b3fb94be5bfa

#practices #article #microservices #en
How Discord Handles Two and Half Million Concurrent Voice Users using WebRTC

https://blog.discord.com/how-discord-handles-two-and-half-million-concurrent-voice-users-using-webrtc-ce01c3187429

В сегодняшней статье от 2018 года команда мессенджер Discord рассказывает про архитектуру их сервиса. Интересно с точки зрения архитектурного кейса организации коммуникации между пользователями.

Статья тезисно:
— Для клиент-серверной коммуникации используется свой собственный фреймворк поверх WebRTC.
— Бэкенд построен на трех китах - Discord Gateway, Discord Guilds и Discord Voice. Клиенты общаются с бэкендом через Discord Gateway. Discord Guilds отвечает за оркестрацию каналов общения по Voice серверам, сам Discord Voice используется непосредственно для обмена контентом между клиентами.
— Guilds серверы для каждого нового пользовательского канала с помощью того же service discovery выбирают наименее загруженный ближайший к пользователю Voice сервер.
— Voice серверы с помощью service discovery репортят свой статус и текущую нагрузку на сервер (используется etcd).
— Клиентам, подключаемым к бэкенду сообщается адрес Voice сервера, на котором живет канал и к которому будут подключаться пользователи.
— Во время отказа Voice сервера, на котором живут каналы, он перестает отправлять свой статус в service discovery, клиенты при этом уведомляются, что сервер недоступен . Guilds сервер выбирает для канала новый Voice сервер, нотифицирует всех клиентов и канал успешно переезжает на другой хост.
— Такая архитектура позволяет достаточно неплохо масштабироваться и распределять нагрузку. На момент написания статьи Discord состоит из 850 Voice серверов в 13 регионах, которые передают более чем 220 Gbps.

#practices #article #startup #en
API Composition
https://microservices.io/patterns/data/api-composition.html

Сегодня достаточно простой, но очень полезный паттерн.
Создавая микросервисную архитектуру и соблюдая стратегию database per service, вы оказываетесь в ситуации, где для того, чтобы собрать даже самый простой, скажем, ответ для клиента, вам требуется сделать запрос в 3, 5 или даже 7 микросервисов. Такую функциональность вам, возможно, нужно даже иметь не в одном месте в коде.

На помощь приходит API Composition pattern. Его цель - скрыть за микросервисом-прокси, называемым API Composer, реализацию сбора информации по нескольким другим микросервисам.
С одной стороны, с помощью дополнительного слоя абстракции, клиенты перестают думать о том разнообразие межсервисного взаимодействия под капотом. С другой стороны, это, хотя и очень легковесная, но все же дополнительная точка отказа.

#pattern #microservices #practices #doc #en
Как мы в Dropbox перешли с Nginx на Envoy

В конце прошлой недели вышла статья о том, как Dropbox перешел с Nginx на Envoy и стал одним из самых больших пользователей Envoy в мире. Значимое событие в индустрии.

Оригинальная статья: https://dropbox.tech/infrastructure/how-we-migrated-dropbox-from-nginx-to-envoy
Перевод: https://habr.com/en/company/southbridge/blog/513504/

#practices #article #backend #highload #ru #en
Безопасность REST API от А до ПИ

Тема, о которой иногда нужно напоминать самим себе — это безопасность. В сегодняшние статье таких напоминаний достаточно много. Автор рассматривает опасные уязвимости при разработке API. О некоторых из них коротко в этом посте:

Недостатки аутентификации пользователей — API2:2019 Broken User Authentication.
Три вида: API key, Basic Authentication, Cookie-Based Authentication, Token-Based Authentication. Рекомендуют использовать последний с access token и refresh token.

Недостатки контроля доступа к объектам — API1:2019 Broken Object Level Authorization.
Все просто. Доступ до вызова DELETE /users/anton должен иметь только пользователь anton или специальная роль, например, "администратор". Если отдаются непубличные данные по ссылке, то ссылку должно быть тяжело подобрать.

Разглашение конфиденциальных данных — API3:2019 Excessive Data Exposure.
Предоставление излишних данных. Например, метод GET /user/anton возвращает ответ на секретный вопрос для восстановления пароля.

Небезопасная десериализация — API6:2019 Mass Assignment.
Недостаточный контроль за входными параметрами. Например, пришедший в запросе json парсится на все поля и они апдейтятся в базе данных. Таким образом, в методе изменения пользователя POST /user/anton можно передать дополнительный атрибут balance и изменить баланс пользователя.

Отсутствие проверок и ограничений — API4:2019 Lack of Resources & Rate Limiting.
Необходимо защитить API от подбора, например, с помощью rate limiter.

Внедрение — API8:2019 Injection.
Подразумевают возможность передать в API параметры, которые выполняются как SQL запрос или команда ОС. Например, метод GET /user/{id}, который внутри делает запрос в базу данных "SELECT FROM USERS WHERE ID={id}" можно использовать как GET /user/1;%20DROP%20TABLE%20USERS и получить смертельный запрос "SELECT FROM USERS WHERE ID=1; DROP TABLE USERS"

Недостатки управления API — API9:2019 Improper Assets Management.
Имеется в виду необходимость контролировать версионность вашего API. В production должны быть доступны только те версии API, которые должны там быть.

Недостатки журналирования и мониторинга — API10:2019 Insufficient Logging & Monitoring.
Речь про то, что нужно мониторить те части системы, что могут пробовать взломать. Например, неудачные попытки авторизации.

Небезопасный транспортный уровень — Insecure Transport.
Передача с помощью HTTP там, где обязательно нужно использовать HTTPS.

Небезопасные пароли — Insecure Passwords.
Не давать задавать небезопасные пароли, не хранить в открытом виде, использовать надежное хэширование.

Небезопасные Cookies и данные в Local Storage — Insecure Cookies and Local Storage.
Нужно помнить, что данные Cookies доступны пользователю. Лучше хранить только служебную информацию.

Использование компонент с известными уязвимостями — Using Components with Known Vulnerabilities.
SDK, frameworks, код с github. Нужно понимать, что сторонние компоненты могут содержать в себе уязвимости.

Межсайтовое выполнение скриптов — CWE-79 Cross-site Scripting (XSS).
Это когда можно вызвать GET /user/<noscript>alert("hacked")</scipt>. Фронтенд попробует написать, что пользователь не найден и на рендеринге исполнит вредоносный скрипт в браузере пользователя.

Межсайтовая подмена запросов — CWE-352 Cross-Site Request Forgery (CSRF).
Предположим, есть финансовая организация с онлайн кабинетом. В Cookies запоминается пользователь, чтобы при входе ему не надо было каждый раз вводить свой логин/пароль. Пользователь случайно заходит на сайт злоумышленника, который отправляет в финансовую организацию транзакцию на перевод денег, в которую браузер автоматически помещает данные из запомненных Cookies.

Кросс-доменное использование ресурсов — Cross-origin resource sharing (CORS).
Можно явно укзаывать поддерживаемые HTTP методы, заголовки и URL, на которых можно вызывать методы API: Access-Control-Allow-Origin: https://example.com:8080

https://habr.com/ru/post/503284/

#article #backend #api #highload #ru
Инцидентный менеджмент или shit happens.
https://medium.com/@AlertOps/the-ultimate-guide-to-incident-management-88b012047a39

В компании, какого бы размера она не была, нужно уметь выносить уроки из произошедших инцидентов (где под инцидентом обычно подразумевают непредвиденные события в сервисе, от которых пострадали пользовательские сценарии, или просто — "страдают пользователи"). Процесс работы с инцидентами называется инцидентным менеджментом.
Кстати, не так давно я писал о об опыте сервиса Ситимобил работы с инцидентами, достаточно интересное чтение.

Мое мнение, что инцидентный менеджмент должен строиться на следующих принципах:
— Когда страдают пользователи, нужно не тратить время на поиск виноватых, а пустить силы на быстрое устранение проблемы.
— Когда происходит инцидент, нужно оценить масштаб трагедии, желательно в количестве пользователей или деньгах. Эта оценка вам даст понимание как конкретно чинить и какими методами. Иногда достаточно в рабочем режиме выкатить релиз с исправлением, а иногда можно и перезагрузить бэкенд с даунтаймом.
— Когда проблема устранена, нужно принять меры для того, чтобы этого больше не повторилось. Обычно в таск-менеджере создается инцидентный таск, который заполняется подробным логом того, что произошло. Нужно на свежую голову ответить на главный вопрос - что мы сделаем, чтобы в будущем этого не повторилось? Ответы на этот вопрос нужно заводить в виде связанных задач.
— Расскажите о ней. Как инструмент прозрачности можно использовать, например, ежемесячные репорты.
— Не вините людей. Часто инцидент — результат стечения многих обстоятельств. Не нужно взгружать кого-то конкретного, это не та культура, которую вы хотите иметь в команде.

И общих рекомендациях:
— Проводите регулярные учения . Учиться преодолевать грабли лучше в режиме, когда все в вооружении.
— Инвестируйте в автоматизацию. Большинство проблем случается из-за человеческого фактора. Чем меньше человеческого фактора будет в ваших проектах, тем реже придется тушить пожары.
— Считайте метрики (например, SLA), это поможет вам держать руку на надежности вашего сервиса и делать выводы до того как вы потеряете много денег.

https://medium.com/@AlertOps/the-ultimate-guide-to-incident-management-88b012047a39
https://medium.com/swlh/incident-management-process-5655ba586cf4
https://www.atlassian.com/incident-management/itsm

#practices #managment #backend #highload #en
btw, Канал не под NDA, в него можно приглашать абсолютно всех по ссылке: https://news.1rj.ru/str/startup_architecture
Можно также поддержать лайком или поделиться постом в FB: https://fb.com/antonskogorev/posts/2398716847093667
Ну а обсудить материал в связанном с каналом чате: https://news.1rj.ru/str/joinchat/CAd00lDH88dDo_Bjkjo5xA
DDD (Domain driven design) или предметно-ориентированное проектирование.

Бывает, что появление нового микросервиса обязано техническими причинами, нежели обусловлено бизнесом. Например, микросервис делится на несколько, потому что в памяти перестают умещаться все кэши.
И хотя вроде бы целью разделения и было уменьшение связанности, но бизнес задачи как-то не ложатся и, например, структура Order живет в тысяче мест и везде значит что-то свое. Потом можно все это дело достаточно много рефакторить, чтобы привести в порядок.

Ключом для избегания таких проблем является подход к проектированию на основе предметной области. Суть его состоит в том, чтобы технические решения описывали бизнесовые сущности, так называемые домены (domains). Эти домены иерархичны — нижние домены описывают более высокоуровневые. Команды могут брать ответственность за домены с понятным скоупом ответственности.
Реализация функциональности затрагивает определенные домены, значит, понятно в кого идти и сколько делать.

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

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

https://medium.com/walmartglobaltech/building-domain-driven-microservices-af688aa1b1b8
https://habr.com/ru/post/428209/
https://martinfowler.com/bliki/BoundedContext.html

Стоит также посмотреть на каноничные труды по Domain Driven Design — книгу Эрика Эванса https://www.ozon.ru/context/detail/id/5497184/

#practices #ddd #microservices #en
DDD Strategic Patterns: How To Define Bounded Contexts

Главные принцип микросервисной архитектуры - слабая связанность и сильное сопряжение. DDD нацелен на достижение этого критерия и одна из ключевых концепций здесь - ограниченный контекст или bounded context.

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

https://codeburst.io/ddd-strategic-patterns-how-to-define-bounded-contexts-2dc70927976e
http://blog.sapiensworks.com/post/2012/04/17/DDD-The-Bounded-Context-Explained.aspx
https://martinfowler.com/bliki/BoundedContext.html

#practices #ddd #microservices #en
Давайте соберем статистику и закроем тему. Вы практикуете DDD?
Anonymous Poll
20%
Да
44%
Нет
36%
Не знаю
Things I Wished More Developers Knew About Databases

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

— Вам повезло, если 99.999% времени нет проблем в сети
— ACID имеет много значений
— Каждая DB имеет разные возможности consistency и isolation
— Оптимистичная блокировка — это вариант, когда вы не можете взять обычную блокировку
— Есть аномалии помимо грязных чтений и потери данных
— Моя база и я не всегда согласны с порядком элементов
— Шардинг на уровне приложения может жить вне приложения
— AUTOINCREMENT может быть вредным
— Устаревшие данные могут быть полезными и lock-free
— Между любыми источниками синхронизации происходят расхождения времени.
— Lantency имеет много значений
— Оцените требования к перформансу каждой транзакции
— Вложенные транзакции могут быть вредными
— Транзакции не должны поддерживать состояние приложения
— Query planners могут сказать много о базах данных
— Онлайн миграции сложные, но возможные
— Значительный рост базы приводит к непредсказуемости

https://medium.com/@rakyll/things-i-wished-more-developers-knew-about-databases-2d0178464f78

#article #databases #medium #en
Books in Software Architecture
https://medium.com/@nvashanin/books-in-software-architecture-6ad974e524ce

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

🥇 Software Architecture in Practice (3rd Edition) (SEI Series in Software Engineering) - Len Bass, Paul Clements, Rick Kazman
🥈 Essential Software Architecture - Ian Gorton
🥈 Patterns of Enterprise Application Architecture - Martin Fowler
🥇 Domain-Driven Design: Tackling Complexity in the Heart of Software - Eric Evans
🥇 Stakeholder Theory: The State of the Art - R. Edward Freeman, Jeffrey S. Harrison, Andrew C. Wicks, Bidhan L. Parmar, Simone de Colle
🥈 Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development - Craig Larman
🥈 Documenting Software Architectures: Views and Beyond - Paul Clements, Felix Bachmann, Len Bass, David Garlan, James Ivers, Reed Little, Paulo Merson, Robert Nord
🥉 Software Systems Architecture: Working With Stakeholders Using Viewpoints and Perspectives - Nick Rozanski, Eóin Woods
🥈 Designing Software Architectures: A Practical Approach (SEI Series in Software Engineering) - Humberto Cervantes, Rick Kazman
🥇 Software Estimation: Demystifying the Black Art - Steve McConnell
🥇 Site Reliability Engineering- Betsy Beyer, Chris Jones, Jennifer Petoff, Niall Richard Murphy
🥉 Enterprise Architecture As Strategy: Creating a Foundation for Business Execution - Jeanne W. Ross, Peter Weill, David Robertson
🥉 Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems - Martin Kleppmann

#books #medium #en

https://medium.com/@nvashanin/books-in-software-architecture-6ad974e524ce
Что же такое этот GraphQL?
https://www.freecodecamp.org/news/so-whats-this-graphql-thing-i-keep-hearing-about-baf4d36c20cf/

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

Простой запрос на GraphQL
 {
posts { # this is an array
noscript
body
author { # we can go deeper!
name
avatarUrl
profileUrl
}
}
}

Основная его особенность и отличие от REST в том, что вам не нужно иметь много разных endpoint'ов, чтобы получить все нужные данные. Интерфейс позволяет иметь единственный endpoint для всего, а клиенты самостоятельно запрашивают только ту информацию, которая им нужна.

Но тогда возникают слишком тяжелые endpoint'ы?- спросите вы. В REST подобную проблему можно было бы решить в помощью API Composition. GraphQL предоставляет инструмент резолверов.

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

Пример резолверов
 {
post(root, args) {
return Posts.find({ id: args.id });
}
},
Post: {
author(post) {
return Users.find({ id: post.authorId})
}
}

Это может быть поход в базу данных или даже запрос в сторонний сервис.

#graphql #microservices #practices #rest #en #ru

https://www.freecodecamp.org/news/so-whats-this-graphql-thing-i-keep-hearing-about-baf4d36c20cf/
(перевод: https://habr.com/en/post/326986/)
https://medium.com/free-code-camp/why-graphql-is-the-future-of-apis-6a900fb0bc81
https://itnext.io/graphql-in-a-microservices-architecture-d17922b886eb