Реализация кэширования на уровне запросов для моих микросервисов - PullRequest
0 голосов
/ 24 июня 2018

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

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

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

В определенный момент времени я получу несколько запросов для вычисления каждого из

{A, T0}, {B, T0}, {C, T0}, {A, B, T0}, {B, C, T0} и т. Д.

Затем мои абоненты переключаются на {A, T1}, {B, T1} и т. Д.

Пока я вычисляю результат для {A, T0} запрос на один узел, кластер получит несколько других запросов на тот же {A, T0} запрос.Даже после того, как я закончу вычислять результат, но до того, как абоненты перейдут на T1, я все равно получу {A, T0} запросов.

Кроме того, запрос {A, B, T0} можно разбить на {A, T0} и {B, T0} запрос плюс простое объединение.

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

Существует ли какая-либо форма кэширования на уровне запросов, которая может облегчить эту ситуацию?

Звучит ли этонемного похоже на попытку сделать POSTs идемпотентными, что может быть невыполнимым.

Набор возможных «букв», указанных выше A, B и C, известен, но большой.Подмножество «букв», которые формируют запросы, могут немного измениться (например, в какой-то момент может быть запрос {A, C, D, T2}).

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

РЕДАКТИРОВАТЬ:

Один из подходов, который я рассматриваю, заключается в следующем:

  • "похожие" запросы получаютнаправляется на тот же узел.Например, все {A, T0} запросов отправляются на узел 12
  • локально, на каждом узле у меня есть (LRU) кэш от Request до Future<Response>
  • , любой запрос либо прослушивает существующий Future или регистрирует и выполняет новый
  • , если узел выйдет из строя, все «похожие» запросы будут назначены другому узлу, и запрос будет обработан снова

Гдеэто становится сложным, имея дело с {A, B, T0} запросами.Они разбиваются на более мелкие запросы, каждый из которых может обрабатываться разными узлами.

1 Ответ

0 голосов
/ 27 июня 2018

Стоит упомянуть, что ваш вопрос слишком широкий.

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


(1) Кэширование ответа (который был вычислен для определенного запроса) и его обработка (без повторного вычисления) снова и снова для идентичных запросов, которые приходят позже.

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

И вам нужно сделать это в многоузловой системе.

Да. На оба ваших вопроса есть ответы.


(1) HTTP-кэширование

Таким образом, вы сомневаетесь в возможности решения многоузловой среды. На самом деле HTTP-кэширование применимо только для промежуточных серверов (Балансы нагрузки, CDN и т. Д.) И браузеров (или мобильных) , а не отдельных узлов .

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

Помимо простого кэширования ответов, есть много других встроенных функций. Для целей кэширования вам потребуется использовать серверное приложение, поддерживающее кеш (например, nginx ) для промежуточных серверов (надеюсь, в вашем сценарии это ваш балансировщик нагрузки). Во всяком случае, большинство из них поддерживают GET запросов по по умолчанию . Но есть также необходимо поработать над поддержкой POST , в зависимости от выбранного вами продукта.

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

(2) Кэш-БД

Вы можете вычислить конкретное значение и сохранить его в кэш-базе данных (которая доступна централизованно для всех узлов). Так что вы можете добавить логику поиска в кэш в ваш код перед выполнением определенного вычисления.

Существует множество приложений для кэширования в памяти, которые удовлетворяют вашим требованиям.

Пример: redis , Hazelcast


Надеюсь, это обернется тем, что вы искали.

...