Масштабирование до 5 млн об/мин

Dec 01 2022
В Trendyol мы несем ответственность за обслуживание содержательных страниц и данных. Мы также предоставляем данные о контенте в виде массива для избранного, коллекций или даже страниц оформления заказа.

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

Каковы наши потребности или ожидаемые нагрузки?

Как и ожидалось, мы обычно получаем больше трафика в сезоны распродаж или во время акций/скидок. В то время как в обычный день мы получаем около 1 млн об/мин (запросов в минуту), в часы пик нагрузка возрастает примерно до 3 млн об/мин. В те времена мы не могли точно соответствовать требованиям. Наше время отклика удвоилось по сравнению с обычным, и у нас даже было больше тайм-аутов, чем мы могли игнорировать.

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

Кому нравятся вызовы? Да, конечно мы :)

Как мы нашли причину проблемы?

Поэтому мы сделали профилирование, чтобы понять, какая часть кода занимает больше времени и использует больше ресурсов. Во-первых, мы использовали профилировщик Java, чтобы сузить круг отслеживаемых частей. После этого мы добавили в код несколько пользовательских трассировок New Relic. Когда мы посмотрели на результаты, мы увидели, что конкретная часть кода отнимала больше всего времени и ресурсов.

Эта часть была логикой преобразования для преобразования документа Couchbase в данные, необходимые нам для выполнения бизнес-логики и использования в качестве массива. Он работал для каждого запроса и каждого контента. Мы начали думать о том, можем ли мы сделать эту логику преобразования асинхронно. Мы могли бы запустить эту логику один раз для каждого контента. На большинство частей ответ был: ДА!

Недостаточно делать все возможное; вы должны знать, что делать, а затем сделать все возможное. — В. Эдвардс Деминг

Можем ли мы обрабатывать данные асинхронно?

Мы используем Couchbase в качестве источника данных. Когда мы рассмотрели, как мы можем асинхронно преобразовывать наши данные Couchbase, мы увидели, что Couchbase имеет протокол изменения базы данных (DCP). DCP может дать нам поток для мутаций. Таким образом, мы можем слушать из нашего старого источника данных, выполнять асинхронное преобразование и записывать в наш новый источник данных. Вы можете проверить статью Ахмета Хатипоглу , если вас интересуют подробности.

Теперь пришло время определить, можем ли мы оптимизировать данные.

Нам нужны все данные?

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

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

Что мы имеем на данный момент?

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

Вы готовы? Мы сохранили 77% данных (1,28 ТБ). Какое облегчение!

Что теперь?

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

Что можно сделать по-другому?

Может быть, технологии, которые мы используем. Старый сервис использовал загрузку Java 8 и Spring. У нас был стабильный опыт работы с Quarkus . Возможно, мы могли бы снизить использование ресурсов и время загрузки, чтобы обеспечить большую масштабируемость. Или мы использовали Flux для получения документов из Couchbase, и, возможно, мы могли бы использовать CompletableFuture для разнообразия. После перечисления наших вариантов мы разработали множество приложений POC и провели множество нагрузочных тестов. Но результаты могли быть и лучше. По крайней мере, не для тех усилий, которые нам понадобятся. Исследования следует продолжить.

Кстати, я уже четыре года суслик. Я считаю, что мы можем эффективно получать документы с помощью параллельных горутин. Так что я хотел попробовать это. Затем я посмотрел официальный Couchbase Go SDK, в котором есть функция «массового получения документов». Это было здорово! Потребности подходили для использования Go. И мне захотелось попробовать оба варианта.

Я провел нагрузочные тесты как для параллельных горутин, так и для массовой функции. Время отклика и использование ресурсов были значительно улучшены для обоих из них. Массовая функция была лучше, чем наша простая реализация. Но что-то было не так. Использование сети было в четыре раза больше. Мы могли бы настроить соединение Couchbase в Java SDK, чтобы включить сжатие. Но Go SDK не имеет конфигурации сжатия в параметрах конфигурации кластера. Поэтому я пропустил соответствующую настройку. К сожалению, функцией сжатия нельзя было управлять с помощью Couchbase Go SDK, в отличие от Couchbase Java SDK. Поэтому я изучил его код, провел мучительную отладку и обнаружил, что сжатием можно управлять с помощью переменной запроса в конце строки подключения.

couchbase://{HOST_HERE}?compression=true

      
                

  • У нас значительно увеличилось использование оперативной памяти, а использование памяти уменьшилось с 800 МБ до 60 МБ на модуль.
  • Время отклика сократилось вдвое. от 10 мс до 5 мс . И он более устойчив против высокой пропускной способности.
  • Использование процессора резко снижается. Чтобы достичь 5 М со старым сервисом, нам нужно было больше стручков. Таким образом, это будет сравнение общего использования ЦП. Теперь 130 ядер вместо 300 .
  • Общий размер документа теперь меньше, чем на четверть, с 1,67 ТБ до всего лишь 386 ГБ .
  • Естественно, нагрузка на сеть намного ниже.
  • Время загрузки теперь составляет 85 миллисекунд вместо 12 секунд !

Спасибо Эмре Одабасу за его поддержку и помощь в написании этой статьи.