이 게시물에서 우리는 감독자를 사용하여 심포니 명령 실행을 처리하는 방법을 배울 것입니다. 기본적으로 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 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/bin/console app:notifications --time-limit=120 --time-between-calls=10 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 구축: 단계별 가이드
부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.
Copyright© 2022 湘ICP备2022001581号-3