Spring @Случайная задержка по фиксированной аннотации
Я использую аннотацию @Scheduled
из фрейма Spring для вызова метода. Но у меня есть несколько узлов в моей настройке, и я не хочу, чтобы все они запускались точно в одно и то же время. Поэтому я хотел бы установить случайное значение для начальной задержки, чтобы компенсировать их друг от друга.
import org.springframework.scheduling.annotation.Scheduled;
@Scheduled(fixedRate = 600000, initialDelay = <random number between 0 and 10 minutes> )
К сожалению, мне разрешено использовать здесь постоянное выражение. Есть ли другой способ обойти это? Я думал об использовании языка выражения Spring.
Ответы
Ответ 1
Вы можете настроить initialDelay с помощью Spring Expression Language:
@Scheduled(fixedRate = 600000, initialDelayString = "#{ T(java.util.concurrent.ThreadLocalRandom).current().nextInt(10*60*1000) }" )
У меня нет IDE для тестирования этого кода прямо сейчас, поэтому, возможно, вам придется немного его адаптировать.
Ответ 2
Чтобы сделать начальную задержку случайным образом где-то между 0 и fixedRate
, попробуйте это:
@Scheduled(fixedDelayString = "${some.delay}", initialDelayString = "${random.int(${some.delay})}")
Где вы определяете some.delay
(но выбираете более подходящее имя) как 10 минут как свойство, подобное вашему приложению .properties или эквивалент.
some.delay = 600000
Конечно, если вы хотите быть ленивым и жестким кодом, вы всегда можете просто использовать ${random.int(600000)}
Ответ 3
Имейте в виду, что initialDelayString оценивается только один раз при запуске, и эти значения используются всегда, когда задание запланировано.
См. org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor # processScheduled
Ответ 4
В этом рабочем примере случайная задержка будет составлять от 5 до 10 секунд.
@Scheduled(fixedDelayString = "#{new Double((T(java.lang.Math).random() + 1) * 5000).intValue()}")
Ответ 5
В котлине это работает:
@Component
class MyJob {
companion object {
const val INTERVAL = 24*3600*1000L // once a day
}
@Scheduled(fixedRate = INTERVAL, initialDelayString = "\${random.long($INTERVAL)}")
fun doDaily() {
...
}
}
Ответ 6
Или вы можете просто добавить Thread.sleep(...) в конце вашей функции.
@Scheduled(fixedDelay = 10000)
public void replicateData() {
... do stuff ...
try {
Thread.sleep(RandomUtils.nextLong(1000, 10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}