Помимо простейшей очереди задач, описанной в предыдущей главе, существует ряд паттернов связывания очередей задач. Простейший из них, когда выходные данные одной очереди ста-новятся входными данными другой очереди, достаточно прост и не требует рассмотрения. Рассмотрим паттерны, которые требуют согласованной работы нескольких очередей задач либо модификации выходных данных одной из очередей. Паттерн Copier
Первый паттерн координации очередей задач — Copier. Задача контейнера-копира — преобразовать исходный поток задач в несколько идентичных параллельных потоков. Этот паттерн полезен, когда над входными данными задачи необходимо вы-полнить несколько различных видов действий. Возьмем, к при-меру, рендеринг видео. Рендеринг может осуществляться во множество различных форматов, в зависимости от того, где видео будет демонстрироваться. Для воспроизведения с жестко-го диска может использоваться разрешение 4K, для потоковой трансляции по сети — 1080p, а для пользователей с медленным мобильным Интернетом — еще более низкое разрешение. Мож-но также сгенерировать анимированную миниатюру в форма-те GIF для использования в интерфейсе плеера. Под каждый 192Часть III. Паттерны проектирования систем пакетных вычислений формат рендеринга будет отведена отдельная очередь, но вход-ные данные для любого исполнителя будут идентичны. Применение паттерна Copier для перекодирования видео схе-матически изображено на рис. 11.2.
Рис. 11.2. Применение паттерна Copier для перекодирования видеоПаттерн Filter
Второй паттерн событийно-ориентированной пакетной обработ-ки называется Filter. Его цель — уменьшить поток задач за счет фильтрации задач, не отвечающих определенным критериям. В качестве примера рассмотрим создание пакетного потока задач, обрабатывающего регистрацию нового пользователя. Некоторые пользователи при регистрации ставят флажок, озна-
чающий их согласие на получение по электронной почте ре-кламных рассылок и другой информации. В таком потоке задач фильтр должен пропускать только тех пользователей, которые явно подписались на получение рассылки. Глава 11. Событийно-ориентированная пакетная обработка 193В идеале контейнер-фильтр следует реализовывать в виде контейнера-посла, обертывающего существующий источник заданий. Исходный источник заданий предоставляет полный список заданий, подлежащих обработке, а контейнер-фильтр сокращает этот список на основе условия фильтрации и вы-дает только те элементы, которые ему удовлетворяют. Пример такого использования паттерна Adapter схематически приведен на рис. 11.3.
Рис. 11.3. Пример реализации паттерна Filter, когда удаляются все нечетныезадания
Паттерн Splitter
Иногда может понадобиться не просто отфильтровать и от-бросить ненужные задачи, а разделить их на два подмноже-ства, каждое из которых попадет в свою очередь. Для такой задачи понадобится контейнер-делитель. Задача делителя, как 194Часть III. Паттерны проектирования систем пакетных вычислений и фильтра, — вычислить значение некоторого критерия. Задачи, не удовлетворяющие данному критерию, в отличие от фильтра, не отсеиваются, а помещаются в другую очередь. Примером приложения паттерна Splitter может служить обра-ботка онлайн-заказов, уведомление о доставке которых поль-зователь получает либо по электронной почте, либо текстовым сообщением. Элементами очереди задач в данном случае станут подлежащие доставке заказы. Контейнер-делитель будет опре-делять каждый заказ в одну из двух очередей — на отправку уве-домления по электронной почте либо текстовым сообщением. Контейнер-делитель может также играть роль копира, отправ-ляющего задачи в несколько очередей. Такое может произойти, когда при оформлении заказа пользователь выбрал оба типа уведомлений. Интересно также отметить, что делитель может быть реализован в виде комбинации копира и двух фильтров. Делитель, однако же, позволяет решить данную задачу более компактным образом.
Читать дальше