Блокировка сервера с балансировкой нагрузки от отправки двух сообщений электронной почты

В настоящее время я работаю над запланированной задачей, которая выполняется за кулисами моего веб-приложения Spring. Задача использует планировщик cron для выполнения в полночь каждую ночь и очистки неиспользуемых приложений для моего портала (Мой сайт позволяет пользователям создавать приложения для заполнения, и если они не получат доступ к форме в течение 30 дней, моя фоновая задача удалит его из нашей БД и сообщит пользователю о создании новой формы, если это необходимо с электронной почтой). Все отлично работает в моей тестовой среде, и я готов перейти на QA.

Однако в моей следующей среде для обработки запросов используются два сервера с балансировкой нагрузки. Это проблема, так как планировщик cron и моя задача опроса выполняются одновременно на обоих серверах. Хотя чтение/запись в БД не будет проблемой, проблема заключается в отправке уведомления по электронной почте пользователю приложения. Без каких-либо блокировок опроса два сообщения электронной почты имеют возможность быть сгенерированы и отправлены, и я хотел бы избежать этого. Обычно мы используем хранимую процедуру SQL и имеем поле в нашей БД для блокировки, а затем устанавливаем/освобождаем каждый раз, когда вызывается код опроса, поэтому будет выполняться только один экземпляр опроса. Однако с моей новой задачей опроса у нас нет доступных полей, поэтому я пытаюсь работать над решением SPRING. Я нашел этот ресурс в интернете:

http://www.springframework.net/doc-latest/reference/html/threading.html

И я думал использовать его как

Semaphore _pollingLock = new Semaphore(1);
_pollingLock.aquire();

try {
    //run my polling task
}
finally {
    //release lock
}

Однако я не уверен, будет ли это просто гарантировать, что второй экземпляр будет выполняться после, или он пропускает второй экземпляр и никогда не будет выполняться. Или это решение даже не подходит, и есть лучшее решение. Опять же, я использую Spring java framework, поэтому любое решение, которое существует, было бы моим лучшим выбором.

1 ответ

  1. В прошлом мы решали подобные проблемы двумя способами: сначала назначали один из наших кластерных серверов ответственным за конкретную задачу (например, отправку электронной почты или выполнение задания).

    В одном решении мы задаем параметр JVM на всех кластерных серверах, определяя имя сервера, на котором должен выполняться процесс. Например-DemailSendServer=clusterMember1

    В другом решении мы просто предоставили параметр JVM при запуске только этого назначенного сервера. Например-DsendEmailFromMe=true

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

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

    Мы не так много сделали с Spring Batch, но я бы предположил, что есть способ настроить пакет для запуска задания на одном сервере в кластере.