Начну с небольшого описания того, как работает мое приложение.
Если пользователь на моем веб-сайте добавляет задачу, задача разбивается на несколько подзадач, количество может варьироваться от 1 до 10 задач. Эти 10 задач добавляются в очередь SQS. У меня есть экземпляр Ubuntu EC2, на котором запущены node.js и docker.
Node.js настроен на прослушивание очереди, и как только он получает сообщение подзадачи, он порождает контейнер докеров, который, в свою очередь, выполняет подзадачу. После выполнения подзадачи контейнер уничтожается.
У меня есть экземпляр c4.2xlarge EC2, который безупречно выполняет вышеуказанный процесс для 1 задачи (10 подзадач). Однако проблема возникает, когда несколько задач добавляются одновременно. Скажем, я провожу тест из 10 задач, которые разбиты на 100 подзадач, сервер испытывает серьезную нагрузку во время запуска контейнеров.
Как мне масштабировать такую среду?
Я думал о резервировании пула остановленных экземпляров EC2, да, «остановлен», потому что задержка для создания нового экземпляра очень велика, и я хотел бы как можно скорее использовать подзадачи в очереди, не неся Стоимость работы сервера 24/7.
Лучше ли писать балансировщик нагрузки в node.js на основе ресурсов / количества сообщений в очереди?
Вам не нужен балансировщик нагрузки. Вам необходимо настроить то, как ваше приложение обрабатывает элементы в очереди.
Сравните ваше приложение с экземплярами разного размера, чтобы определить оптимальное / максимальное количество задач, которые оно может обрабатывать одновременно. Для иллюстрации предположим, что это число - 20.
Измените свое приложение, чтобы вытащить из очереди не более 20 элементов, никогда больше. Когда одна из ваших 20 подзадач будет выполнена, она может вернуться в очередь для выполнения других.
На этом этапе ваш единственный рабочий сервер не должен «перегружаться». Просто потребуется время, чтобы проработать большую очередь элементов.
Такой лимит нужен вам, чтобы предотвратить вашу «сильную нагрузку при спуске контейнеров».
Получив это, вы можете сделать некоторые оптимизации:
Вам нужно каждый раз создавать новые контейнеры, или вы можете использовать их повторно? Это позволит сэкономить несколько циклов процессора при обработке подзадачи.
Вы можете использовать экземпляры EC2 в остановленном состоянии вместо создания новых экземпляров. Но для этого вам нужно будет выполнить индивидуальную обработку вашего предупреждения CloudWatch, но это можно сделать. Вы хотите, чтобы слушатель в SNS ожидал предупреждений, после чего он может запускать и останавливать экземпляры EC2 по мере необходимости.
Протестируйте свое приложение, используя экземпляры разных размеров. Возможно, лучше использовать два c4.xlarge, чем один c4.2xlarge. Экспериментируйте и пробуйте разные комбинации.
Теперь это можно сделать с помощью бессерверной технологии, функций AWS Lambda и AWS SNS или SQS.
https://aws.amazon.com/lambda/
Например, Задача может запускать SNS, который может отправить его в Lambda, где ваша функция будет автоматически масштабироваться в зависимости от спроса.