Лучший подход для веб-приложения Java для вызова внешнего API только 4 раза в день (с учетом перехода на летнее время)

У нас есть серверная веб-служба Java, работающая на 2 производственных серверах с 2 JVM на каждом из них, за балансировщиком нагрузки на сервере приложений Websphere.

Мой вариант использования:

  • Вызов внешнего API в первый раз после развертывания.
  • If Response.OK
    • Cache the response in an external datastore (not relevant for this question)
  • For the next client requests of the day and if the time of the requests are not equal to or immediately after a set of times (9:00, 11:00, 13:00, 15:00)
    • Return the cached response
  • If the client request happens to be on any given time in the set (9:00, 11:00, 13:00, 15:00)
    • Call the external API and update cache (not relevant again). Example., request comes at 9:00
  • For all the subsequent requests from 9:00 to 10:59 (because next time in the set is 11:00)
    • Return the cached response
  • At 11:00
    • Call the external API and update cache
  • И так далее..

Таким образом, в день выполняется только четыре запроса к внешнему API, а не прямой вызов внешнего API для каждого запроса.

Как я могу добиться этого на уровне приложения на Java на всех производственных серверах, учитывая переход на летнее время в определенном часовом поясе, без какого-либо сетевого программирования или программирования ввода-вывода?

Примечание. Приложение не использует загрузку Spring. Я пытаюсь сделать это исключительно на Java.


person Barani    schedule 15.05.2021    source источник
comment
Вы проверили stackoverflow.com/questions/11840059/   -  person sanjeevRm    schedule 15.05.2021
comment
Отвечает ли это на ваш вопрос? Как запустить программу Java под cron и импортируйте банки   -  person sanjeevRm    schedule 15.05.2021
comment
@sanjeevRm Я посмотрю на выполнение заданий cron Sanjeev, но должен быть какой-то способ сделать это без каких-либо зависимостей от внешних библиотек и только на Java, например, с помощью службы запланированного исполнителя или UUID типа 4.   -  person Barani    schedule 15.05.2021
comment
вы можете запланировать задачу в java, используя java.util.Timer и java.util.TimerTask , у таймера есть метод schedule, это связано с потоком, может усложниться, если не обрабатывается должным образом   -  person sanjeevRm    schedule 15.05.2021
comment
Вы ограничены 4 вызовами на jvm или 4 вызовами на все JVM? Если это 4 на JVM, проще всего было бы передать ваше время (9,11..) в качестве параметров и просто сохранить время последнего вызова в кеше и обновить кеш, если он старше (блок обновления синхронизации). Если это всего 4 вызова для всех ваших JVM, вам нужно будет использовать общий кеш и более сложную логику обновления, чтобы разрешить только одно одновременное обновление.   -  person Gas    schedule 17.05.2021
comment
@Gas.. Это не ограничение, а скорее попытка сэкономить. Было бы действительно хорошо, если бы на всех JVM и серверах было только 4 вызова. Но и 8 исходящих звонков (4 запроса х 2 сервера, с приложением в одной JVM каждый) тоже было бы не так уж и плохо. Когда вы упоминаете общий кеш, вы имеете в виду кеширование на сервере? Если да, то я не за этим. Но как мы можем добиться одновременного обновления или даже обновления для каждого сервера?   -  person Barani    schedule 18.05.2021
comment
@Barani, может быть, я что-то упустил ... но вы просто проксируете вызовы внешнего API через свой сервис. Эта служба кэширует ответ и проверяет, не устарел ли результат, и если это так, он вызывает внешний API. Уровень синхронизации зависит от того, хотите ли вы иметь кеш сервера или общий доступ (например, через db, redis или что-то подобное). Если на сервере, то блокировка может быть выполнена внутри jvm (синхронизированный блок), в противном случае через блокировки БД. Пока один поток выполняет обновление, остальные обслуживают все еще кэшированный ответ.   -  person Gas    schedule 18.05.2021
comment
@Gas.. Это имеет смысл. Сохранение значения блокировки во внешней базе данных и принятие решения о том, когда обновлять блокировку в приложении. Если запрос выполняется через 9 или несколько минут после этого, установите значение блокировки в false с добавленным временем запроса, чтобы это указывало на то, что пришло время для вызова API и обновления кеша, а затем в конце установите блокировку значение true, все в синхронном исполнении. Надеюсь, я думаю в том же направлении, что и вы. Но что происходит, когда есть два одновременных запроса в 9:00? Как обеспечить параллелизм здесь?   -  person Barani    schedule 20.05.2021
comment
@Gas.. А что происходит, когда это первый запрос после развертывания приложения? Нам нужно будет вызвать внешний API хотя бы один раз в первый раз. Допустим, мы установили другое значение в базе данных для первого запроса и установили его в true. Но это будет означать, что база данных будет независимой от приложения... т. е. мы должны убедиться, что мы устанавливаем значение первого запроса равным true каждый раз, когда приложение развертывается, а затем устанавливаем его в false позже в приложении. Есть ли лучший способ справиться с этим?   -  person Barani    schedule 20.05.2021
comment
@Barani Когда вы звоните в БД, вы делаете Select for update, в этом случае только один поток сможет получить блокировку, выполнить вызов, обновить кеш, снять блокировку. Другие параллельные потоки будут ожидать блокировки записи. Да, во время первого запуска, если вы запускаете много приложений одновременно, другое может ждать, пока первое не получит значение, но позже, если один поток заметит, что кеш просто обновляется, он просто вернет устаревшие данные в последний раз. , или дождитесь завершения обновления, в зависимости от ваших требований.   -  person Gas    schedule 21.05.2021