Hasura Storage в Go: 5-кратное увеличение производительности и на 40% меньше оперативной памяти

Hasura Storage — это сервис с открытым исходным кодом, который соединяет любой S3-совместимый облачный сервис хранения данных с Hasura, и именно этот сервис мы, в Nhost, используем для предоставления возможностей хранения данных нашим пользователям.

Его цель — позволить пользователям объединить функции, которые они любят в Hasura (разрешения, события, действия, предустановки и т.д.), с удобством демонстрации файлов онлайн.

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

Для тех, у кого мало времени, цель этой статьи в блоге — продемонстрировать выигрыш, который мы получили по всем показателям, переписав микросервис Node.js на Golang. Выигрыш включает в себя 5-кратное увеличение количества обслуживаемых запросов при сокращении потребления памяти вдвое.

Решение переписать сервис

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

  1. Его система управления зависимостями и система сборки идеально подходят для облака.
  2. У команды Nhost было много опыта работы с Golang.
  3. Несмотря на то, что это очень многословный язык, особенно по сравнению с Node.js, он очень прост в изучении и быстр в написании.
  4. Он известен как очень производительный

Если вам интересно узнать больше о языке и его обещаниях, в ACM есть хорошая статья об этом.

Переписывание сервиса

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

Бенчмаркинг сервиса

Когда переработка была завершена, мы решили провести несколько тестов на Node.js и Golang версиях сервиса. Для этого мы использовали k6 и разработали следующий тест:

  1. Когда тест запускается, он увеличивает количество рабочих от 1 до TARGET в течение первых 10 секунд.
  2. Затем он работает еще 60 секунд, после чего сворачивается.
  3. Рабочие запрашивают сервис как можно быстрее
  4. Мы провели следующие тесты:
  5. CPU был ограничен 10% от общей производительности системы
  6. Оперативная память была неограниченной

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

Количество запросов

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

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

Потребление оперативной памяти

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

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

Время отклика

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

Давайте начнем с рассмотрения минимального времени отклика:

Это трудно увидеть в тестовом примере download_small_file, но мы улучшили время отклика в этом сценарии с 29 мс в случае Node.js до 7 мс в случае Golang. Это 4-кратное улучшение, которое мы наблюдаем во всех остальных сценариях, кроме download_image_manipulated, где мы видим примерно 2-кратное улучшение. (об этом сценарии мы поговорим позже).

А теперь давайте посмотрим на P95

Здесь мы также видим 4-кратное улучшение для большинства случаев, за исключением download_image_manipulated и download_large_file, где мы видим существенное улучшение, но не такое значительное, как в остальных случаях. Это имеет смысл, поскольку загрузка больших файлов будет связана с I/O NET, в то время как работа с изображениями будет связана с CPU, но даже в этом случае мы рады видеть это существенное улучшение.

Манипулирование изображениями

Я хотел выделить случай download_image_manipulated, поскольку это интересный случай. По соображениям производительности обе версии Hasura Storage полагаются на библиотеку C под названием libvips, именно по этой причине Node.js работает здесь довольно хорошо, несмотря на ограничения процессора, которые мы ввели. Однако приятно видеть, что даже осознавая, что оба сервиса используют одну и ту же базовую библиотеку C, нам удалось значительно улучшить все показатели.

Развертывание сервиса в производство

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

Как видите, мы сократили объем памяти почти на 40%, что является значительным улучшением, которое позволит нам обслуживать больше пользователей и трафика без увеличения общих расходов на инфраструктуру.

Заключение

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

Оцените статью
Procodings.ru
Добавить комментарий