Я создаю веб-приложение, которое предоставляет в качестве основной функции возможность пользователям загружать большие изображения и обрабатывать их. Обработка занимает примерно 3 минуты, и я подумал, что Heroku станет идеальной платформой для возможности запуска этих рабочих мест по требованию и с высокой степенью масштабируемости. Сама задача обработки довольно дорого стоит вычислить, и ей необходимо запустить высокопроизводительный PX-динамик. Я хочу максимизировать распараллеливание и свести к минимуму (эффективно устранить) время ожидания задания в очереди. Другими словами, я хочу иметь N PX-динамиков для N заданий.
К счастью, я могу сделать это довольно легко с помощью API Heroku (или, необязательно, такого сервиса, как Hirefire). Всякий раз, когда приходит новый запрос обработки, я могу просто увеличить счетчик рабочих, и новый рабочий захватит задание из очереди и начнет немедленно обрабатывать.
Однако, хотя масштабирование безболезненно, сокращение начинается там, где начинается проблема. API Heroku разочаровывает. Я могу установить только количество работающих сотрудников, а не убивать простое. Это означает, что, если у меня есть 20 рабочих, каждый из которых обрабатывает изображение, и один выполняет свою задачу, я не могу безопасно масштабировать счетчик работ до 19, потому что Heroku убьет произвольного рабочего динозавра, независимо от того, действительно ли он находится в середине задания! Оставляя всех работающих до тех пор, пока все рабочие места не закончатся, просто не может быть и речи, потому что стоимость будет астрономической. Представьте, что 100 рабочих, созданных во время всплеска, продолжали бездействовать на неопределенный срок, так как в течение дня было несколько новых рабочих мест!
Я просмотрел веб-страницы, и лучшее "решение", которое люди предлагают, - это то, что ваш рабочий процесс грамотно обрабатывает завершение. Хорошо, что отлично, если ваш рабочий просто делает массовое рассылку, но мои работники делают очень затянутую аналитику на изображениях, и, как я уже упоминал выше, займите около 3 минут.
В идеальном мире я могу убить конкретного рабочего динозатора после завершения его задачи. Это упростит масштабирование так же просто, как и масштабирование.
На самом деле, я приблизился к этому идеальному миру, переключившись с рабочих динозавров на однократные (которые заканчиваются на завершение процесса, т.е. вы прекращаете платить за dyno после выхода из него "корневой программы" ). Тем не менее, Heroku устанавливает жесткий предел 5 одноразовых динамиков, которые могут запускаться одновременно. Это я могу понять, поскольку я, безусловно, в некотором смысле злоупотреблял одноразовыми динамиками... но это все равно разочаровывает.
Есть ли способ, которым я могу лучше уменьшить моих рабочих? Я бы предпочел не переустраивать мой алгоритм обработки... разбивая его на несколько кусков, которые работают через 30-40 секунд, в отличие от одного 3-минутного растяжения (таким образом, случайное убийство работающего работника не было бы катастрофический). Такой подход резко усложнит мой код обработки и представит несколько новых точек отказа. Однако, если это мой единственный вариант, мне придется это сделать.
Любые идеи или мысли оценены!