#java #scheduled-tasks #okhttp
#java #запланированные задачи #okhttp
Вопрос:
Я хочу отправить несколько параллельных HTTP-запросов (например, через асинхронный OkHttp) в очень точное временное окно (например, с 20.08.2020 00.00.00 по 20.08.2020 00.00.50) .
http://www.quartz-scheduler.org имеет точность до 1 секунды.
Как их запланировать?
Комментарии:
1. Вы можете создать
ScheduledExecutorService
с помощьюExecutors.newScheduledThreadPool(..)
и и использовать его для точного планирования выполнения. Если вам нужно нечто большее (что-то вроде Quartz, с сохраняемостью и т.д.), Вы можете реализовать свою собственную логику вокругScheduledExecutorService
, например, он загружает сериализованные расписания выполнения из базы данных при запуске вашего приложения и так далее.
Ответ №1:
Если вас волнует время их получения сервером, в отличие от того, когда клиент начинает отправку, тогда вам следует предварительно прогреть OkHttp с некоторыми запросами.
Для подключений по протоколу HTTP / 1.1 требуется несколько подключений. Проверьте размер пула соединений и настройте его при необходимости.
Для подключения HTTP / 2 готово, когда вы переходите к отправке результатов. Если вас беспокоит размер какого-либо одного запроса, вы можете переопределить поведение OkHttp по умолчанию, используя несколько клиентских экземпляров, чтобы избежать блокировки заголовка строки в общем сокете.
Как предлагалось выше, для планирования потоков Java используйте ScheduledExecutorService и, вероятно, просыпайтесь перед событием и запускайтесь с точностью до миллисекунды. Вы не можете использовать nanoTime, поскольку оно относится к произвольной эпохе, поэтому точность в миллисекундах, вероятно, лучшее, что вы можете сделать.
Комментарии:
1.
As suggested above, for java thread scheduling use ScheduledExecutorService and probably wake before the event and spin until the exact millisecond.
— Я не совсем понимаю, как достичь такой точности. Как оценить «время пробуждения» и достичь желаемого эффекта в требуемом временном окне? Не могли бы вы предоставить какой-либо PoC, пожалуйста?2. Вероятно, будет проще, если вы приведете пример того, что вы пытались в исходном вопросе, чтобы другие могли помочь вам с вашей конкретной проблемой. В противном случае существует множество предположений, например, отправляются ли они на один и тот же хост, загружают ли они файлы или запрашивают head.
3. Я проверял несколько разных библиотек JAVA schedulers, но максимальная детализация, которую я мог получить, находится на уровне секунд. Я проверил Quartz Scheduler, Fulcrum Quartz из Apache Turbine, cron4j, но пока безуспешно
Ответ №2:
Вы можете использовать планирование задачи в Java в CompletableFuture, чтобы запланировать свою задачу: что-то вроде этого для планирования вашей http-задачи:
TimeUnit можно использовать для планирования с точностью до миллисекунд.(TimeUnit.МИЛЛИСЕКУНДЫ)
public static <T> CompletableFuture<T> schedule(
ScheduledExecutorService executor,
Supplier<T> command,
long delay,
TimeUnit unit
) {
CompletableFuture<T> completableFuture = new CompletableFuture<>();
executor.schedule(
(() -> {
try {
return completableFuture.complete(command.get());
} catch (Throwable t) {
return completableFuture.completeExceptionally(t);
}
}),
delay,
unit
);
return completableFuture;
}
Обратитесь к этой статье за концепцией для completablefuture:
Альтернативно вы можете написать свой собственный планировщик:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html
Редактировать:
Попробуйте использовать это: scheduleWithFixedDelay (запускаемая команда, длительное начальное время, длительная задержка, единица измерения времени)
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("America/Los_Angeles"));
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
LocalDateTime ldt= LocalDateTime.parse("2020-10-17T12:42:04.000", formatter);
ZonedDateTime nextRun= ldt.atZone(ZoneId.of("America/Los_Angeles"));
if(now.compareTo(nextRun) > 0)
nextRun = nextRun.plusDays(1);
Duration duration = Duration.between(now, nextRun);
long initalDelay = duration.toMillis();
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(new MyRunnableTask(),
initalDelay,
TimeUnit.DAYS.toMillis(1),
TimeUnit.MILLISECONDS);
Комментарии:
1. Я не уверен, где именно в вашем предлагаемом решении я должен установить точную дату и время для отправки запроса. Я могу видеть
delay
иunit
, но, к сожалению, нет никакой точки отсчета во времени. Пожалуйста, объясните, как использовать ваше решение для желаемого временного окна из вопроса.2. Пожалуйста, проверьте раздел редактирования, если это решит вашу проблему.