cron-job.org 실행 실패 및 자동 정지(Disabled) 문제 해결 방법
크론 서비스 자동 정지 문제 해결 방안
1. 발생 문제 cron-job.org 같은 외부 크론 서비스는 요청 후 일정 시간(보통 30초) 내에 응답이 오지 않으면 실패(Failure)로 간주합니다. 특히 전기차 충전소 데이터처럼 처리량이 많은 API 작업은 응답 시간이 길어질 수밖에 없는데, 실패가 누적되면 "the cronjob will be disabled because of too many failures" 정책에 따라 해당 크론잡이 아예 비활성화되어 자동화가 멈추게 됩니다.
2. 해결 원리 (비동기 처리) 이 문제를 해결하기 위해 호출부와 실행부를 물리적으로 분리하는 비동기 핸들링 방식을 적용합니다.
- b.php (호출부): 외부 크론 서비스의 요청을 대신 받는 게이트웨이입니다. 서버 내부의
a.php에 실행 신호만 던진 뒤, 작업 완료를 기다리지 않고 즉시 HTTP 200 성공 응답을 반환합니다. 이로 인해 외부 서비스는 항상 1초 이내에 성공한 것으로 인식하여 자동 정지를 방지합니다. - a.php (실행부): 실제 데이터 처리 로직을 담당합니다. 호출부와의 연결이 끊겨도 백그라운드에서 프로세스가 끝까지 유지되도록 설정합니다.
3. 핵심 코드 구성
[a.php: 백그라운드 프로세스 보장]
// 클라이언트(b.php)의 연결이 끊겨도 스크립트 실행을 유지
ignore_user_abort(true);
// 대량 데이터 처리를 위해 실행 시간 제한(Default 30s)을 해제
set_time_limit(0);
// 실제 DB Update 로직 및 진행 상황 로그 기록
error_log("[STATUS] Update Started", 3, "./cron_log.txt");
[b.php: 즉시 응답 및 트리거]
// fsockopen을 사용하여 a.php에 GET 요청 전송 후 즉시 fclose
$fp = fsockopen($host, 80, $errno, $errstr, 5);
if ($fp) {
fwrite($fp, "GET /a.php HTTP/1.1\r\nHost: $host\r\nConnection: Close\r\n\r\n");
fclose($fp);
echo "Success"; // cron-job.org에 즉시 반환되는 결과
}
4. 기대 효과 이 구조를 통해 외부 크론 서비스의 타임아웃 제한과 상관없이 대용량 데이터 갱신 작업을 안정적으로 수행할 수 있으며, 관리자는 cron_log.txt를 통해 백그라운드 작업의 최종 성공 여부를 별도로 모니터링할 수 있습니다.