Активировать пакет только на одном экземпляре сервера - PullRequest
1 голос
/ 14 февраля 2020

У меня есть балансировщик нагрузки nginx перед двумя экземплярами tomcat, каждый из которых содержит приложение весенней загрузки. Каждое весеннее загрузочное приложение выполняет пакет, который записывает данные в базу данных. Пакет выполняется каждый день в 1:00. Проблема в том, что оба экземпляра выполняют пакет одновременно, а я не хочу.

Есть ли способ сохранить развернутые пакеты в двух экземплярах и сказать tomcat или nginx, чтобы запустить пакет на главном сервере ( и ведомый сервер не запускает пакет).

Если один из серверов останавливается, второй сервер может запустить пакет от его имени.

Есть ли инструмент в nginx или tomcat (или какая-то другая технология) для этого?

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 24 февраля 2020

Если вы спроектируете два экземпляра сервера приложений для одновременного выполнения одного и того же задания, то один из них по своему замыслу создаст экземпляр экземпляра задания, а другой не удастся (и этот сбой можно игнорировать). См. Javado c из JobRepository . Это одна из ролей репозитория заданий: действовать в качестве защиты от повторных выполнений заданий в кластерной среде.

Если один из серверов останавливается, второй сервер может запустить пакет на своем от имени. Есть ли в nginx или tomcat (или какой-либо другой технологии) инструмент для этого?

Я считаю, что такой инструмент или технология не нужны. Если один из серверов выйдет из строя во время графика, другой сможет принять решение и успешно запустить задание.

1 голос
/ 14 февраля 2020

Вот упрощенный подход c.

Поскольку у вас есть два запланированных метода в двух виртуальных машинах, запущенных одновременно, добавьте случайную задержку к обеим. В этом ответе есть много вариантов, как отложить запуск на случайную длительность. Spring @ Запланированная случайная задержка аннотации

Внутри метода запускайте задание, только если оно НЕ запущено (другой ВМ). Это можно сделать с помощью новой таблицы для отслеживания этого.

Вот псевдокод для этой схемы:

@Scheduled(cron = "schedule expression")
public void batchUpdateMethod() {
     //Check database for signs of job running now.
     if (job is not running){
         //update database table to indicate job is running
         //Run the batch job
         //update database table to indicate job is finished
     }
}

База данных или какое-либо общее расположение файла должно использоваться в качестве синхронизировать c между двумя запусками, поскольку две виртуальные машины не зависят друг от друга.

Для более надежной конструкции рассмотрим Spring Batch Spring Batch использует базу данных для своих заданий (JobsRepository). По умолчанию источник данных в памяти используется для отслеживания запущенных заданий и их состояния. В вашей настройке 2 экземпляра (скорее всего) используют свои собственные в базе данных памяти. Несколько экземпляров Spring Batch могут координироваться друг с другом как кластер, и один может запускать задания, а другой - создавать резервные копии actasa, если база данных jobsRepository является общей. Для этого вам нужно настроить 2 экземпляра на использование общего источника данных.

Вот несколько документов: https://docs.spring.io/spring-batch/docs/current/reference/html/index-single.html#jobrepository

https://docs.spring.io/spring-batch/docs/current/reference/html/job.html#configuringJobRepository

...