Много маленьких запросов против нескольких больших запросов (API Design)

49

В настоящее время я работаю над проектом с организацией следующим образом:

  • Клиент - получает данные с главного сервера через REST API.
  • Сервер - запрашивает данные с других серверов через сторонние API
  • Сторонние API - не зависящие от меня сервисы, предоставляющие данные на сервер (Reddit, Hackernews, Quora и т. Д.)

В качестве аргумента, скажем, клиенту сначала нужен список элементов из каждого стороннего API. Из этого списка будет выбран элемент, и в этот момент клиент должен увидеть полное содержимое элемента, а также ответы (то есть комментарии) на элемент. Я пытаюсь выбрать между тремя вариантами:

А ля карт

При таком подходе у меня будет 3 отдельных конечных точки на моем сервере: одна для получения списка элементов, одна для получения основного контента для элемента и одна для получения ответов элемента.

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

Серверный кеш

В этом запросе я бы сделал один вызов на мой сервер, чтобы «извлечь» все данные для всех источников. Затем данные будут кэшироваться на сервере. Тогда клиент будет иметь те же конечные точки REST, что и раньше, за исключением того, что между вызовами не будет много ожидания, так как мой сервер уже имеет данные и просто должен передать их клиенту.

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

Клиентский кеш

Этот сценарий похож на предыдущий, за исключением того, что клиент делает только один запрос к серверу: предоставьте мне все данные. Отсюда ответственность за сохранение данных и их правильное использование лежит на клиенте.

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

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

williamg
источник
Мне кажется, это выбор между свежестью и скоростью. Что предпочитают ваши заинтересованные стороны и конечные пользователи?
Эрк

Ответы:

28

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

Недавно я участвовал в проекте коллективного веб-приложения на основе базы данных, в котором одна из команд находится в Индии (остальные в США). У нас есть один экземпляр базы данных, размещенный в нашем офисе в США, к которому разработчики подключают экземпляры нашего локального веб-сервера. Мой рабочий стол может быть в пятидесяти футах и ​​двух прыжках локальной сети от экземпляра базы данных, и производительность в порядке.

Когда мы впервые начали работать с разработчиками в Индии, они испытывали огромное время ожидания при запуске приложения и переходе от страницы к странице. Мы говорим здесь десять минут ожидания. Оказывается, это произошло потому, что время пинга ~ 200 мс от их рабочих столов до нашего сервера базы данных dev умножалось на множество кратких запросов к базе данных. Мой локальный пинг 0,5 мс был настолько тривиальным, что общение между веб-сервером и сервером базы данных никогда не имело значения. Это был первый раз, когда у нас было географическое разделение между веб-сервером и сервером базы данных.

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

JakeRobb
источник
2

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

wfdctrl
источник
1

На основании только информации, которую вы дали, вариант 1, потому что

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

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

guillaume31
источник
0

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

Фрэнк Хилман
источник
0

Я бы (почти) сделал скидку на вариант 3. Выбор между 1 и 2 зависит от двух вещей:

  • (A) насколько велик результат одной полной выборки
  • (B) сколько деталей результата клиент / пользователь обычно использует в этом сеансе.

Легко принять решение, если А и В - крайности:

  • Если A большое, а B маленькое, определенно выберите вариант 1 (A la Carte).
  • Если A мало, а B велико, выберите 2 (кэш на стороне сервера) или даже 3 (кэш на стороне клиента).

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

Кизил Массон
источник
0

Как всегда в программировании, это зависит.

Итак, реальный вопрос: что вы должны учитывать при выборе A / B / C или их комбинации?

Я бы сказал, что реальными различающими факторами являются детали реализации сторонних API, которые вы используете. В качестве примера вы должны рассмотреть: они быстрые или медленные? Изменяются ли данные часто и неожиданно? Они "болтливы" или отдыхают?

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

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

Вариант 3 я бы рассмотрел, только если данных не много, но в этом случае даже варианты 1 или 2 могут работать, и вы сохраняете больше логики на сервере, поэтому я бы придерживался 1 или 2.

Просто мой 2с.

А. Кьеза
источник