이 게시물에서는 supervisord를 사용하여 심포니 명령 실행을 처리하는 방법을 알아보겠습니다. 기본적으로 감독자는 다음을 허용합니다.
때때로 우리는 프로세스 실행을 자동화하기 위해 Unix crontab을 사용합니다. 이는 대부분의 경우 작동할 수 있지만 문제를 일으킬 수 있는 상황이 있을 수 있습니다.
사용자 알림을 기록하는 데이터베이스 테이블이 있다고 가정해 보겠습니다. 테이블에는 다음 정보가 저장됩니다.
반면에 다음 단계에 따라 실행되는 명령을 코딩했습니다.
Linux crontab에서 이 명령이 자주(1분, 2분 등) 실행되도록 설정했습니다. 지금까지는 너무 좋았습니다.
이제 현재 프로세스가 500개의 알림을 쿼리했고 400개를 보냈을 때 새 프로세스가 시작된다고 가정해 보겠습니다. 이는 새 프로세스가 마지막 프로세스와 새 프로세스에 의해 아직 업데이트되지 않은 100개의 알림을 쿼리한다는 것을 의미합니다.
두 프로세스 모두에서 쿼리했기 때문에 100개의 알림이 두 번 전송될 수 있습니다.
해결책으로 감독자를 사용할 수 있습니다. 프로세스를 계속 실행하고 필요할 때 다시 시작합니다. 이렇게 하면 하나의 프로세스만 유지하고 중복을 피할 수 있습니다. 명령이 어떻게 보이는지 분석해 보겠습니다.
#[AsCommand( name: 'app:notification' )] class NotificationCommand extends Command { private bool $forceFinish = false; protected function configure(): void { $this ->addOption('time-limit', null, InputOption::VALUE_OPTIONAL, 'Max time alive in seconds') ->addOption('time-between-calls', null, InputOption::VALUE_OPTIONAL, 'Time between every loop call') ; } protected function execute(InputInterface $input, OutputInterface $output): int { $this->forceFinish = false; pcntl_signal(SIGTERM, [$this, 'signalHandler']); pcntl_signal(SIGINT, [$this, 'signalHandler']); $timeLimit = $input->getOption('time-limit'); $timeBetweenCalls = $input->getOption('time-between-calls'); $dtMax = (new \DateTimeImmutable())->add(\DateInterval::createFromDateString("+ {$timeLimit} seconds")); do{ // Here we should execute a service to query and send notifications // ...... sleep($timeBetweenCalls); $dtCurrent = new \DateTimeImmutable(); }while($dtCurrent < $dtMax && !$this->forceFinish); return Command::SUCCESS; } public function signalHandler(int $signalNumber): void { echo 'Signal catch: ' . $signalNumber . PHP_EOL; match ($signalNumber) { SIGTERM, SIGINT => $this->forceFinish = true, default => null }; } }
명령어를 단계별로 설명해 보겠습니다.
configure 메소드는 입력 옵션을 선언합니다.
execute 메소드는 다음과 같이 동작합니다:
signalHandler 함수는 SIGTERM 및 SIGINT Unix 신호를 포착합니다. SIGINT는 Ctrl+C를 누를 때 전송되는 신호이고 SIGTERM은 kill 명령을 사용할 때 기본 신호입니다. signalHandler 함수가 이를 감지하면 forceFinish 변수를 true로 설정하여 현재 루프가 끝나면 명령이 종료됩니다. forceFinish 변수는 다음과 같습니다. 더 이상 거짓이 아닙니다. 이를 통해 사용자는 최대 날짜가 완료될 때까지 기다리지 않고 프로세스를 종료할 수 있습니다.
지금까지 명령어가 생성되었습니다. 이제 이를 처리할 수 있도록 감독자를 설정해야 합니다. 구성을 시작하기 전에 감독자를 설치해야 합니다. 다음 명령을 실행하면 됩니다:
sudo apt update && sudo apt install supervisor
설치 후 다음 명령을 실행하여 감독자가 실행 중인지 확인할 수 있습니다.
sudo systemctl status supervisor
감독자 구성 파일은 /etc/supervisor/conf.d 폴더에 있습니다. notif.conf라는 파일을 만들고 다음 내용을 붙여넣습니다.
command=php <your_project_folder>/bin/console app:notifications --time-limit=120 --time-between-calls=10 user=<your_user> numprocs=1 autostart=true autorestart=true process_name=%(program_name)s_%(process_num)02d
각 키를 설명해 보겠습니다.
이 구성을 사용하면 app:notifications 명령이 최대 120초 동안 실행되며 매 루프 후 10초 동안 절전 모드로 전환됩니다. 120초가 경과하거나 Unix 신호를 캐싱한 후 명령은 루프를 종료하고 완료됩니다. 그러면 감독님이 다시 시작하겠습니다.
우리는 crontab을 사용하지 않고도 감독자를 사용하여 명령을 계속 실행하는 방법을 배웠습니다. 이는 crontab에 의해 시작된 프로세스가 중복되어 데이터 손상을 일으킬 수 있는 경우 유용할 수 있습니다.
제가 쓴 마지막 책에서는 관리자를 사용하여 심포니 메신저 작업자를 계속 실행하는 방법을 보여주었습니다. 더 자세히 알고 싶으시면 여기에서 책을 찾아보실 수 있습니다: PHP 및 Symfony 프레임워크를 사용하여 작업 지향 API 구축: 단계별 가이드
위 내용은 Supervisor를 사용하여 Symfony 명령 실행 처리의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!