@Scheduled с fixedRate — задачи наслаиваются друг на друга
@Scheduled(fixedRate = 5000) запускает следующий вызов через 5 секунд после старта предыдущего, независимо от того, закончился он или нет. Если задача обычно выполняется 2 секунды, а один раз — из-за лока в БД или медленного внешнего вызова — 20 секунд, следующие запуски не отменяются, они копятся в очереди планировщика.
По умолчанию Spring использует однопоточный TaskScheduler с пулом размера 1. Значит, накопленные вызовы не выполняются параллельно — они выстраиваются в очередь и срабатывают подряд, один за другим, как только предыдущий закончился. Со стороны это выглядит как сервис, который внезапно начинает бомбить внешний API или БД пачкой запросов.
fixedDelay отличается тем, что отсчитывает интервал от завершения предыдущего запуска, а не от его старта — при долгой задаче наложения не будет вообще, просто следующий запуск сдвинется по времени.
@Scheduled(fixedDelay = 5000) public void syncOrders() { // следующий запуск через 5 сек // после завершения этого метода }
На собеседовании часто спрашивают не про сам fixedRate, а про то, что происходит, если задача виснет надолго — например, ждёт лок на строке в Postgres. Правильный ответ включает и настройку пула scheduler'а: если он однопоточный, зависшая задача блокирует не только свои повторы, но и все остальные @Scheduled методы в приложении, если они используют тот же дефолтный TaskScheduler.
fixedRate считает от старта, fixedDelay — от завершения. Для задач с непредсказуемой длительностью fixedDelay безопаснее почти всегда.
Тренажёр: 600 вопросов, мок с таймером, план повторов
senior·base — что спрашивают на самом деле
В этом посте были ссылки, но мы их удалили по правилам Сетки
· 22.08
shedlock поверх @scheduled, если сервис крутится в нескольких подах — без него fixeddelay не спасает, каждый инстанс всё равно запускает задачу независимо. одна аннотация + таблица в постгресе, и дубли уходят без отдельного планировщика. для большинства кейсов это проще и скучнее, чем городить quartz или выносить cron наружу
0
ответить
коммент скрыт — часть юзеров считает его токсичным или некорректным
коммент удалён
· 25.08
И автоматом получаем узкое место при горизонтальном масштабировании, если шедулим критически важный функционал(( нарвались на такое недавно при построении новой системы. Придется как-то разделять запуски шедулера из разных под, чтобы их действия не наслаивались
0
ответить
коммент скрыт — часть юзеров считает его токсичным или некорректным
ответ удалён
· вчера
ShedLock тут делает ровно одно: «задача выполняется один раз, а не по разу на под». Узкое место, о котором говорит Михаил, — это уже другая задача: если сама работа тяжёлая, её надо не блокировать, а резать — шардировать по ключу (hash(id) % подов) или по диапазону, чтобы каждый под брал свой кусок и они не пересекались. Блокировка тогда остаётся только на общие шаги, а не на весь объём.
0
ответить
коммент скрыт — часть юзеров считает его токсичным или некорректным
ответ удалён
· 10 ч
Спасибо за перефразировку ☺️ все так
0
ответить
коммент скрыт — часть юзеров считает его токсичным или некорректным
ответ удалён