Найти тему
Oracle APEX

Падающий FTP сервер

Внешний сервер Oracle собирает некоторую информацию и должен по расписанию отправить данные на FTP сервер в главном офисе - а он, этот FTP сервер, периодически падает. Что делать?

Изначально был некий процесс по cron'у, который в час X запускал FTP процесс. Если передача была успешной, отправлялось письмо с отчетом; если соединение с FTP сервером не устанавливалось, то отправлялось письмо с уведомлением об ошибке FTP.

Потом стало понятно, что за доступностью FTP сервера стоит следить постоянно, записывать в базу интервалы простоя и, вероятно, отправлять письма о начале и завершении инцидента. Что и было сделано.

А еще через некоторое время стало понятно, что разовая попытка отправки данных в течение суток надежной не является: FTP сервер может "лежать" как раз в это время, и письмо об этом прискорбном событии вряд ли может быть достаточным утешением при потере данных за сутки. Нужно было придумать что-то адаптивное.

Лобовой подход выглядел примерно так:

  1. Запускаем по cron'у разовый процесс в час X;
  2. Если соединение с FTP сервером провалилось, то запускаем новый полинговый процесс, который пытается установить соединение и осуществить передачу данных через интервалы времени Y.

Масса переделок. Посидели, подумали. "Стой! Ничего не делай! Нужно найти такое решение, чтоб ничего не делать, а результат получить." Т.е. нужно было придумать алгоритм, который бы ничего не делал, кроме случая возможности и нужности FTP передачи данных. И очень желательно без переделок существующего кода.

Поступили так:

  • У нас постоянно идет процесс пинга на FTP сервер и мы более-менее точно знаем, живой ли он в данный момент времени;
  • Запускаем периодический и довольно частый процесс попытки отправки данных на FTP сервер, но с условиями:
  • Если текущее время меньше X, - ничего не делаем, ибо рано;
  • Если у нас открытая проблема пинга на FTP сервер, - ничего не делаем, ибо без толку;
  • Если FTP передача сегодня у нас уже была, - ничего не делаем, ибо поздно;
  • В противном случае даем команду на попытку FTP передачи, ибо в самый раз!

Все решения мы, конечно, примем в базе данных, откуда "в код" передадим лишь решение, надо ли начинать попытку FTP передачи. Для этого мы в Oracle напишем простой пакет, проверяющий частные условия и принимающий руководящее для кода решение:

function is_time(p_h number, p_m number default 0) return number; -- -1(/0)/1

-- проверка, не рано ли?

function is_on_problem return number; -- 0/1

-- проверка, не над проблемой ли мы?

function was_today_ftp(p_h number, p_m number default 0) return number; -- 0/1

-- проверка, не отправляли ли уже сегодня?

function try_ftp(p_h number, p_m number default 0) return number -- 0/1 (1 = go!)
as
begin
if is_time(p_h, p_m) >= 0 and is_on_problem = 0 and was_today_ftp(p_h, p_m) = 0
then return 1;
else return 0;
end if;
end try_ftp;

-- принятие решения об уместной попытке FTP передачи.

А далее мы просто охватываем существующий код FTP транспорта условием типа

if ($try_ftp == 1)
{
... // существующий код отправки
}

И всё.

Добрый пример того, как сделать многое по принципу "почти ничего не делать".