Руководитель видит, что готовые задания не разбираются, и первая мысль — добавить обработчиков. Иногда покупка честная. Часто то же ожидание просто копируется на большее число процессов. Очередь — это работа, которая ещё не закончилась. Сама по себе она не доказывает, что потребителей мало. Прежде чем добавлять обработчиков, отделите то, что ждёт запуска, от того, что падает, от того, что висит на замке, и от того, что никто не берёт, потому что процессы, за которые вы уже платите, не запущены.
Текст для человека, который может открыть очередь и машину с обработчиками. Это не наплыв на кеш после истечения ключа, не процесс, который растёт, пока машина его не убьёт, не довод ставить Node рядом с Laravel и не чтение журнала медленных запросов. У каждой из этих беды своя проверка. Если пропустить разложение ниже, больший пул только сделает не ту проблему громче.
1. Разложите затор по состояниям
Считайте четыре кучи, не один график. Готовые: свободный обработчик может взять их сейчас. Отложенные: они должны подождать до времени, которое вы сами задали. Зарезервированные: обработчик уже взял и ещё не закончил или не отпустил. Сбойные: они упали и либо лежат отдельно, либо вернутся в готовые по расписанию повтора. Одна «глубина» прячет, какая куча растёт. Новые обработчики разбирают готовую работу. Они не лечат сбойную кучу и не приближают отложенное задание к его часу.
Запишите числа вместе с часами. Посмотрите ещё раз через тихие десять минут, без выкладки посередине. Если готовых много, а зарезервированных почти ноль, работу никто не берёт. Если зарезервированные держатся высоко, а готовых мало, обработчики заняты или застряли: добавлять есть смысл только когда это живая работа, а не замок. Если сбойные растут, а готовые выглядят спокойно, это не нехватка мощности. Это задание, которое ошибается. Назовите очередь. Общая очередь для писем, выгрузок и вебхуков покажет одну глубину на три разные работы. Глубину лучше читать по имени очереди или задания. Починка застрявшей выгрузки — не починка вебхука, который партнёр отклоняет снова и снова.
2. Найдите имя задания, которому принадлежит глубина
Откройте выборку готовых и сгруппируйте по типу. Одна выгрузка, одна пересборка изображений или один повтор вебхука часто держат почти все строки. Остальной продукт при этом спокоен. Предложение удвоить весь парк — это предложение масштабировать одно задание, которое ещё никто не прочитал. Прочитайте одну полезную нагрузку этого типа: какой идентификатор она несёт, какой кабинет, если он есть, и какой внешний вызов делает. Куча одинаковых повторов в один сломанный адрес — не нагрузка, а одна ошибка, повторённая много раз. Этот тип надо отложить или починить до новых обработчиков. Иначе каждый новый процесс пристаёт к тому же повтору.
Отдельно посмотрите возраст самого старого готового задания, не только счётчик. Тысяча заданий за последнюю минуту — это всплеск. Сотня, из которых самому старому шесть часов, — это хвост, который не успевает, или обработчик, который остановился. Всплеск может требовать более медленного производителя. Шестичасовой хвост требует живого обработчика или задания, которое вообще заканчивается.
3. Посмотрите одно зарезервированное задание
Возьмите задание, которое висит в резерве дольше своего обычного времени, и посмотрите, на чём оно ждёт. Замок у другого обработчика. HTTP без предела по времени. Запрос, который сначала надо было прочитать в журнале медленных, а не в разговоре о числе процессов. Файл на диске, который уже полон. Больше обработчиков умножает ожидание замка. Они также умножают вызовы к партнёру, который и так режет частоту.
Предел по времени входит в этот осмотр. Задание без границы может сидеть в резерве, пока процесс убьёт что-то другое. Очередь по-прежнему считает его взятым. Новые обработчики стартуют, а застрявшее держит слот. Поставьте границу под саму работу и решите, что значит истечение времени: повтор или сбой с текстом, который человек прочитает. Повтор без границы — это как затор сам себя наполняет. Если ожидание — это запрос, остановитесь. Новые потребители будут выполнять его чаще. Соседняя проверка — как читать журнал медленных запросов до рефакторинга. Если внутри одного процесса растёт память, это другая форма, не затор очереди. Обработчиков вместо любого из этих чтений не покупают.
4. Повтор умеет подделать нехватку мощности
Полезная нагрузка, которая падает каждый раз и возвращается в готовые, выглядит как глубина. Обработчик занят. Счётчик не падает. Ошибка — та же строка. Это ядовитое задание. Больше обработчиков переваривают яд быстрее и всё равно его не заканчивают. Ограничьте попытки. После предела оставьте запись в хранилище сбоев, которое человек может открыть, с последней ошибкой и идентификатором. В готовые не возвращайте, пока кто-то не изменит данные или обработчик.
На заданиях, которые всё же заканчиваются, посмотрите счётчик попыток. Здоровое заканчивается с первого раза. То, которому часто нужны три, уже говорит, что обработчик или партнёр нестабилен. Масштабировать процессы до этого чтения — значит платить за повторы. И повышать шанс двойного эффекта, если обработчик небезопасно запускать дважды. Второй запуск, который снова списывает деньги, шлёт письмо или вставляет строку, хуже затора. Среда выполнения этой безопасности не даёт. Обработчик должен записать результат и остановиться, когда та же работа приходит снова. Сбои, на которые никто не смотрит, становятся второй очередью. Если команда видит только готовых, хранилище сбоев может расти неделю. Один взгляд на сбои ставьте рядом со взглядом на готовых. Если боль именно там, следующий найм — не обработчик, а починка или решение выбросить тип, который вы не можете завершить.
5. Посчитайте обработчиков, которые уже должны быть
Спросите, сколько процессов должно работать, и посчитайте, сколько работает. Менеджер процессов может обещать четыре и иметь ноль после выкладки, падения или машины, которая их так и не подняла. Готовых становится больше, потому что к очереди никто не подключён. Пятая строка в документе не запускает первые четыре. Проверьте машину, которая, по-вашему, потребляет очередь. Проверьте, что это та среда, которой очередь принадлежит, а не забытый тестовый ящик, направленный в тот же брокер.
У очереди на базе данных есть вторая ловушка. Обработчики опрашивают. Если они живы, но спят по длинному расписанию, глубина готовых остаётся, хотя «обработчики подняты». Сон укорачивайте только после того, как поймёте, что заглядывать в задания дёшево. Чаще опрашивать кучу яда всё равно не значит её закончить. Не путайте это с наплывом на кеш и со второй средой выполнения. Ключ, который истёк и который пересчитывает каждый запрос, — это наплыв, а не затор заданий. Процесс на Node рядом с вебом — решение о границе, оно в заметке про очередь вне Laravel. Ни одно из них не начинается с фразы «добавим обработчиков» к куче, которую вы ещё не назвали.
6. Когда новые обработчики — честный ответ
Добавляйте потребителей, когда проверки выше скучные. Готовых стабильно много. Зарезервированные заканчиваются в своё обычное время. Сбои тихие. Самое старое готовое задание стареет, а те обработчики, что есть, действительно заняты полезной работой. Обработчик безопасно запускать дважды. Партнёр выдерживает дополнительные вызовы, или частоту вы уже ограничили. Тогда больший пул сокращает ожидание. Запишите число готовых, возраст самого старого и число обработчиков до и после, чтобы следующий человек видел, что добавление было заработано. Если производитель обгоняет любой пул, который вы готовы держать, новые обработчики только отодвигают разговор. Замедлите производителя, соберите работу пакетами или откажитесь от типа задания. Затор без границы — это решение продукта в костюме инфраструктуры.
Когда звать помощь
Разложить готовые, отложенные, зарезервированные и сбойные можно за одно сидение, и одну ядовитую нагрузку тоже можно прочитать. Помощь нужна, когда глубина настоящая, обработчики живы, а вы всё равно не видите, какое имя задания держит ожидание. И когда повтор может дважды списать деньги или отправить письмо, а никто не доказал, что обработчик останавливается. И когда две машины могут потреблять одну очередь, и непонятно, какая из них жива. Работа в том, чтобы назвать кучу до того, как платить за больший пул.
Услуги закрывают такое чтение на уже существующем Laravel или Node: какое задание наполняет очередь, почему оно не заканчивается и обработчик ли здесь лекарство. Избранные работы держат каждое измерение рядом со своей операцией. Очередь, которая растёт сама по себе, не лечится ещё одним обработчиком, так что направление производительности и масштабируемости начинается с чтения очереди: какое задание её наполняет, почему она встаёт и сколько обработчиков нужно на самом деле. Если напишете, пришлите имя очереди, четыре счётчика, тип, который доминирует, и запущены ли те потребители, на которых вы рассчитываете. Полезную нагрузку клиентов в первое письмо не кладите.