Labutin
@Labutin
Web-разработчик

Должен ли worker сам определять, обрабатывать ему задачу или нет?

С коллегой возник следующий спор.
Представим ситуацию.
Есть задача - неким способом обработать входной файл. Бизнес логика такая, что файл можно разбить на части и обрабатывать из независимо.
Архитектура следующая.
Обработчик файла делит его на куски и в очередь (в нашем случае в RabbitMQ) шлет сообщения типа "обработай кусочек вот этих данных". Worker'ы забирают задачи из очереди и трудятся. Причем самим Worker'ам нет необходимости знать что-то еще о других частях большого файла. Им достаточно их кусочка.
Обработав все кусочки у нас в результате складывается общий результат обработки исходного файла.
Файлы регулярно приходят от разных пользователей. Все обрабатывается и все довольны.
До этого момента все гладко.
Теперь про сложность.
Бизнес логика такая, что если пользователь отправил на обработку за короткий срок два входных файла, то результат обработки второго по времени файла затирает первый. По сути, первый можно было бы вообще не обрабатывать.
Но по хронологии событий в очереди уже есть задачи на обработку кусков первого файла. И в ту же очередь приходят задачи на обработку второго файла. Получается Worker'ы вхолостую перемолотят первый файл и тут же возьмутся за второй. Но это только часть проблемы.
Сейчас я постараюсь объяснить как можно проще вторую часть проблемы.
Как я выше написал, обработка кусков файла настолько независима, что как только один Worker обработал свою часть файла, то эта часть уже видна другим пользователям.
Упростим ситуацию.
Пусть входной файл можно разбить на две части: А и Б
После обработки бы получились результат А' и Б' который видят другие пользователи.
Представим, что пользователь с небольшим промежутком отправил на обработку два файла их двух частей:
А и Б
В и Г
Очередь будет такой
А Б В Г
Далее хронология такая:
А взял на обработку Worker1
Б взял на обработку Worker2
Worker1 справился и выдал результат А'
Worker2 задумался
В взял на обработку Worker3
Г взял на обработку Worker1
-----
Очередь пуста
-----
Worker3 справился и выдал результат B'
Worker1 справился и выдал результат Г'
---------
Клиенты видят результат В'Г' - все хорошо
Вспоминаем про Worker2 - он задумался и упал и сообщение (Б) обратно ВЕРНУЛОСЬ в очередь
Первый свободный Worker его подхватил и выдал результат Б' который перезатирает Г'
В результате пользователи видят B'Б' (один кусок от старого входного файла).

Надеюсь, что не сильно запутал.

И вот наконец-то мы добрались к сути вопроса! Как такое избежать?
Вариант 1:
Тот, кто кладет в очередь ждет, пока предыдущий файл полностью обработается. Но тогда Worker'ы как бы вхолостую перемолотят старые данные и тут же им пойдут задачи с новыми данными.

Вариант 2:
Каким-то способом изъять из очереди уже ненужные задачи.

Вариант 3:
Worker, получая задачу, как-то умеет определять, нужно ли обрабатывать этот кусок данных или он уже старый и неактуальный и тогда он ничего не делает и берет следующее сообщение из очереди.
Причем в описанном примере определить достаточно просто. В очередь сообщений можно вместе с информацией о куске, который нужно обработать передать ID файла (уникальный). И Worker может дернуть, например, какой-то REST сервис, передав туда ID файла и узнать - были ли более свежие файлы от этого пользователя? И если были, то уже нет смысла обрабатывать этот кусок файла.

Я склоняюсь к варианту 3. Но мой коллега говорит, что Worker должен быть максимально прост и никакой логики определения нужно ли обрабатывать задачу из очереди или нет в нем не должно быть. Т.е. взял задачу из очереди - молоти.

А как бы вы поступили в данной ситуации?
  • Вопрос задан
  • 259 просмотров
Пригласить эксперта
Ответы на вопрос 1
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Очередью должен управлять менеджер очереди, именно он знает от кого поступило новое задание и надо ли удалять необработанные фрагменты предыдущего задания из очереди. Worker просто получает очередное задание и не должен просматривать всю очередь, а без такого просмотра он не в состоянии определить, есть в очереди более свежее задание от того же пользователя или нет. Максимум - Worker может получать команду от менеджера на досрочное прерывание обработки, если обрабатываемая им задача уже не нужна.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы