Как отправить HTTP-запрос в очень точное время в JAVA

#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://www.artificialworlds.net/blog/2019/04/05/scheduling-a-task-in-java-within-a-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. Пожалуйста, проверьте раздел редактирования, если это решит вашу проблему.