Узнайте, как Node масштабируется вместе с ЦП

Я слышал, как многие говорят, что приложения следует масштабировать по горизонтали, а не по вертикали, но действительно ли это лучший способ масштабирования? В этой статье мы рассмотрим, как Node.js масштабируется вместе с ЦП, и посмотрим, есть ли что-то еще, что нам нужно принять во внимание, если мы это сделаем.

Инфраструктура тестирования

Для тестирования Node.js было создано демонстрационное приложение с конечными точками, которые можно было использовать для имитации нагрузки. Приложение Dockerized и его можно найти на Docker Hub. Исходный код можно найти на GitHub.

Приложение было развернуто на AWS ECS с разными ограничениями ЦП, а перед ним был поставлен балансировщик нагрузки, чтобы сделать его общедоступным. Код, используемый для развертывания этой инфраструктуры, можно найти на GitHub. Если вы хотите развернуть его самостоятельно, проверьте репозиторий и запустите yarn build, чтобы создать стек CloudFormation. Затем запустите yarn cdk deploy. Различные экземпляры развернуты в <loadbalancer DNS>/<CPU>, где ЦП - один из 256, 512, 1024 или 2048. Как только вы закончите, вы можете удалить все с помощью yarn cdk delete.

Нагрузочный тест

Артиллерия использовалась для нагрузочного тестирования приложения, начиная с одного запроса в секунду (RPS) и наращивая до 40 запросов в секунду за четыре минуты. Медленно увеличивая скорость в течение четырех минут, мы можем более точно увидеть, в какой момент приложение начинает давать сбой. Это повторялось четыре раза - по одному разу для каждого размера процессора. Артиллерийский файл и результаты всех тестов можно найти на GitHub. Вы найдете .html файлов, которые можно загрузить, чтобы увидеть графики. Если вам нужен необработанный вывод, посмотрите .json файлы в том же каталоге. Конечная точка, которая была протестирована, вычисляла 30-е число Фибоначчи. Это вычислительно дорогостоящая задача для выполнения, имитирующая реальное приложение, выполняющее работу.

Графики ниже взяты из теста 512 CPU. Задержка и количество одновременных пользователей остаются неизменными в первой части теста. Это показывает, что приложение работает хорошо и справляется с нагрузкой. Как только служба становится перегруженной, увеличивается время ожидания и количество одновременных пользователей. Обратите внимание, как количество одновременных пользователей увеличивается экспоненциально. Задержка также резко увеличивается с примерно 50 мс до более пяти секунд после того, как служба достигла своего предела. Как только служба получает запросы быстрее, чем она может обработать, запросы копируются, что замедляет работу службы и вызывает резервное копирование большего количества запросов.

Полученные результаты

Построив точку, в которой каждый тест ЦП начал давать сбой (когда количество одновременных пользователей и время отклика увеличились), мы видим, что Node.js линейно масштабируется с ЦП. Это означает, что в большинстве случаев нет никакой выгоды с точки зрения количества запросов в секунду на ЦП для увеличения ЦП. На приведенном ниже графике это показано. Обратите внимание, что нет увеличения между 1024 и 2048. Это связано с однопоточным характером Node. Дополнительный ЦП простаивает. AWS Fargate взимает плату за частичный виртуальный ЦП, поэтому четыре 256 модуля равны цене одного 1024 модуля. Таким образом, создание более крупных контейнеров не приносит финансовой выгоды.

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

Преимущества горизонтального масштабирования

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

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

Увеличивая объем трафика, мы также повышаем отказоустойчивость. Если модуль выходит из строя, нагрузка распределяется между все еще работающими модулями. Если у нас есть десять модулей, обрабатывающих 10 запросов в секунду каждый, и один выйдет из строя, оставшиеся девять модулей получат только 1,1 RPS. Если у нас будет только пять из них, обслуживающих 10 запросов в секунду, а один выйдет из строя, остальные поды получат 2,5 запроса в секунду. Этого могло быть достаточно, чтобы перегрузить службу. Наличие большего количества модулей также распределяет нагрузку на большее количество зон доступности и узлов, если они доступны.

Заключение

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

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