Хотя есть принятый ответ, есть несколько простых, доморощенных решений, в которых нет ошибок, как вы описали выше.Решение wget хорошо работает для обеспечения того, чтобы код выполнялся на одном сервере, но добавляет проблемы безопасности (вы должны защитить URL с помощью общего закрытого ключа доступа), и, как указал @sourcedelica, также вопрос о том, какой сервер должен затем вызыватьЗадача cron.
Я склоняюсь к решению, которое работает независимо от количества систем, которые у вас есть, а также не требует разных конфигураций cron для разных систем.
Предположениечто в будущем вы можете добавить новые машины, и ваш основной сервер (например, сконфигурированный для запуска вашей задачи cron) может умереть или быть остановленным.
Разработанное мной решение использует блокировки базы данных кластера, которыеможет быть сделано с двумя простыми таблицами:
CREATE TABLE `Server` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uname` varchar(32) NOT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`alive` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `Lock` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`code` varchar(128) NOT NULL,
`pid` int(10) unsigned DEFAULT NULL,
`server` int(10) unsigned DEFAULT NULL,
`locked` timestamp NULL DEFAULT NULL,
`used` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `code` (`code`)
);
Каждая система имеет уникальный uname
и регистрирует запись, если она не существует;обновляя alive
каждый раз.
Чтобы получить замок:
SELECT * FROM Lock WHERE code='cron-cluster';
Если его не существует,
INSERT INTO `Lock` ...
Как только вы получите Lock
с id
из 32.Если server
и pid
оба равны NULL, задайте им для моего сервера id
и текущий идентификатор процесса, используя атомарную природу базы данных, чтобы обеспечить только один.
UPDATE Lock SET server=1,pid=4233 WHERE id=32 AND server IS NULL and pid IS NULL;
Затем вы делаетевыберите еще раз, чтобы увидеть, действительно ли вы его приобрели (при условии, что n разных машин пытаются получить блокировку одновременно):
SELECT COUNT(id) FROM Lock WHERE code='cron-cluster' AND server=1 AND pid=4233;
Если результат равен 1, вы получаете блокировку, 0означает, что это сделал другой процесс.
Последнее, что нужно сделать, это очистить каждый сервер от мертвых блокировок и мертвых серверов;каждый сервер отвечает за проверку того, что активный процесс запущен для каждого заблокированного Lock
, а когда Server
не обновляется как alive
по истечении определенного времени, удалите все блокировки, связанные с этим сервером и его Server
запись.
Я добавил другие свойства сервера в таблицу Server
, чтобы разрешить мониторинг дискового пространства, процессора и т. д.
Хотя он не такой мощный, как кластеризация Quartz, он решает вашу проблему.