Laravel Horizon
소개
Laravel Horizon을 자세히 알아보기 전에 Laravel의 기본 큐 서비스에 익숙해져야 합니다. Horizon은 Laravel에서 제공하는 기본 큐 기능에 이미 익숙하지 않으면 혼란스러울 수 있는 추가 기능으로 Laravel의 큐를 강화합니다.
Laravel Horizon은 Laravel로 구동되는 Redis 큐를 위한 아름다운 대시보드와 코드 기반 구성을 제공합니다. Horizon을 사용하면 작업 처리량, 런타임 및 작업 실패와 같은 큐 시스템의 주요 메트릭을 쉽게 모니터링할 수 있습니다.
Horizon을 사용할 때 모든 큐 작업자 구성은 단일의 간단한 구성 파일에 저장됩니다. 버전 제어된 파일에 애플리케이션의 작업자 구성을 정의함으로써 애플리케이션을 배포할 때 애플리케이션의 큐 작업자를 쉽게 확장하거나 수정할 수 있습니다.
설치
Laravel Horizon은 큐를 구동하기 위해 Redis를 사용해야 합니다. 따라서 애플리케이션의 config/queue.php 구성 파일에서 큐 연결이 redis로 설정되어 있는지 확인해야 합니다.
Composer 패키지 관리자를 사용하여 Horizon을 프로젝트에 설치할 수 있습니다.
composer require laravel/horizon
Horizon을 설치한 후, horizon:install Artisan 명령어를 사용하여 해당 자산을 게시하십시오:
php artisan horizon:install
구성
Horizon의 assets을 게시한 후, 기본 구성 파일은 config/horizon.php에 위치하게 됩니다. 이 구성 파일을 통해 애플리케이션의 큐 워커 옵션을 구성할 수 있습니다. 각 구성 옵션에는 해당 목적에 대한 설명이 포함되어 있으므로, 이 파일을 꼼꼼히 살펴보십시오.
Horizon은 내부적으로 horizon이라는 Redis 연결을 사용합니다. 이 Redis 연결 이름은 예약되어 있으며, database.php 구성 파일이나 horizon.php 구성 파일의 use 옵션 값으로 다른 Redis 연결에 할당해서는 안 됩니다.
환경
설치 후, 가장 먼저 숙지해야 할 Horizon 구성 옵션은 environments 구성 옵션입니다. 이 구성 옵션은 애플리케이션이 실행되는 환경의 배열이며, 각 환경에 대한 워커 프로세스 옵션을 정의합니다. 기본적으로 이 항목에는 production 및 local 환경이 포함되어 있습니다. 그러나 필요에 따라 더 많은 환경을 자유롭게 추가할 수 있습니다:
'environments' => [ 'production' => [ 'supervisor-1' => [ 'maxProcesses' => 10, 'balanceMaxShift' => 1, 'balanceCooldown' => 3, ], ], 'local' => [ 'supervisor-1' => [ 'maxProcesses' => 3, ], ],],
일치하는 다른 환경이 없을 때 사용될 와일드카드 환경 (*)을 정의할 수도 있습니다:
'environments' => [ // ... '*' => [ 'supervisor-1' => [ 'maxProcesses' => 3, ], ],],
Horizon을 시작하면 애플리케이션이 실행 중인 환경에 대한 워커 프로세스 구성 옵션을 사용합니다. 일반적으로 환경은 APP_ENV 환경 변수 값에 의해 결정됩니다. 예를 들어, 기본 local Horizon 환경은 3개의 워커 프로세스를 시작하고 각 큐에 할당된 워커 프로세스 수를 자동으로 조정하도록 구성되어 있습니다. 기본 production 환경은 최대 10개의 워커 프로세스를 시작하고 각 큐에 할당된 워커 프로세스 수를 자동으로 조정하도록 구성되어 있습니다.
horizon 구성 파일의 environments 부분에 Horizon을 실행하려는 각 환경에 대한 항목이 있는지 확인해야 합니다.
Supervisors (감독자)
Horizon의 기본 구성 파일에서 볼 수 있듯이 각 환경에는 하나 이상의 "감독자"가 포함될 수 있습니다. 기본적으로 구성 파일은 이 감독자를 supervisor-1로 정의하지만, 원하는 대로 감독자 이름을 자유롭게 지정할 수 있습니다. 각 감독자는 기본적으로 워커 프로세스 그룹을 "감독"하는 역할을 하며, 큐에 걸쳐 워커 프로세스의 균형을 맞추는 것을 담당합니다.
해당 환경에서 실행되어야 하는 새로운 워커 프로세스 그룹을 정의하고 싶다면, 특정 환경에 추가 감독자를 추가할 수 있습니다. 애플리케이션에서 사용하는 특정 큐에 대해 다른 밸런싱 전략 또는 워커 프로세스 수를 정의하고 싶을 때 이 방법을 선택할 수 있습니다.
유지 관리 모드
애플리케이션이 유지 관리 모드에 있는 동안, Horizon 구성 파일 내에서 감독자의 force 옵션이 true로 정의되지 않은 한 큐에 대기 중인 작업은 Horizon에 의해 처리되지 않습니다:
'environments' => [ 'production' => [ 'supervisor-1' => [ // ... 'force' => true, ], ],],
기본값
Horizon의 기본 구성 파일에서 defaults 구성 옵션을 볼 수 있습니다. 이 구성 옵션은 애플리케이션의 감독자에 대한 기본값을 지정합니다. 감독자의 기본 구성 값은 각 환경의 감독자 구성에 병합되므로, 감독자를 정의할 때 불필요한 반복을 피할 수 있습니다.
밸런싱 전략
Laravel의 기본 큐 시스템과 달리, Horizon에서는 simple, auto, false 세 가지 워커 밸런싱 전략 중에서 선택할 수 있습니다. simple 전략은 들어오는 작업을 워커 프로세스 간에 균등하게 분할합니다:
'balance' => 'simple',
구성 파일의 기본값인 auto 전략은 큐의 현재 워크로드에 따라 큐당 워커 프로세스 수를 조정합니다. 예를 들어, notifications 큐에 1,000개의 보류 중인 작업이 있는 반면 render 큐가 비어 있다면, Horizon은 큐가 비워질 때까지 notifications 큐에 더 많은 워커를 할당합니다.
auto 전략을 사용할 때, 큐당 최소 프로세스 수와 Horizon이 총 확장 및 축소해야 하는 최대 워커 프로세스 수를 제어하기 위해 minProcesses 및 maxProcesses 구성 옵션을 정의할 수 있습니다:
'environments' => [ 'production' => [ 'supervisor-1' => [ 'connection' => 'redis', 'queue' => ['default'], 'balance' => 'auto', 'autoScalingStrategy' => 'time', 'minProcesses' => 1, 'maxProcesses' => 10, 'balanceMaxShift' => 1, 'balanceCooldown' => 3, 'tries' => 3, ], ],],
autoScalingStrategy 구성 값은 Horizon이 큐를 지우는 데 걸리는 총 시간 (time 전략) 또는 큐의 총 작업 수 (size 전략)를 기준으로 큐에 더 많은 워커 프로세스를 할당할지 여부를 결정합니다.
balanceMaxShift 및 balanceCooldown 구성 값은 Horizon이 워커 수요를 충족하기 위해 얼마나 빨리 확장되는지 결정합니다. 위의 예에서는 최대 1개의 새 프로세스가 3초마다 생성 또는 삭제됩니다. 필요에 따라 애플리케이션의 요구 사항에 따라 이 값을 자유롭게 조정할 수 있습니다.
balance 옵션이 false로 설정되면 기본 Laravel 동작이 사용되며, 구성에 나열된 순서대로 큐가 처리됩니다.
대시보드 인증
Horizon 대시보드는 /horizon 경로를 통해 액세스할 수 있습니다. 기본적으로 local 환경에서만 이 대시보드에 액세스할 수 있습니다. 그러나 app/Providers/HorizonServiceProvider.php 파일 내에 인증 게이트 정의가 있습니다. 이 인증 게이트는 로컬이 아닌 환경에서 Horizon에 대한 액세스를 제어합니다. Horizon 설치에 대한 액세스를 제한하기 위해 필요에 따라 이 게이트를 자유롭게 수정할 수 있습니다:
/** * Horizon 게이트를 등록합니다. * * 이 게이트는 로컬이 아닌 환경에서 누가 Horizon에 액세스할 수 있는지 결정합니다. */protected function gate(): void{ Gate::define('viewHorizon', function (User $user) { return in_array($user->email, [ ]); });}
대체 인증 전략
Laravel은 자동으로 인증된 사용자를 게이트 클로저에 삽입한다는 것을 기억하십시오. 애플리케이션이 IP 제한과 같은 다른 방법을 통해 Horizon 보안을 제공하는 경우, Horizon 사용자가 "로그인"할 필요가 없을 수 있습니다. 따라서 Laravel이 인증을 요구하지 않도록 위의 function (User $user) 클로저 서명을 function (User $user = null)로 변경해야 합니다.
무음 처리된 작업
애플리케이션 또는 타사 패키지에서 발송한 특정 작업을 보는 데 관심이 없을 수 있습니다. 이러한 작업이 "완료된 작업" 목록에서 공간을 차지하는 대신, 해당 작업을 무음 처리할 수 있습니다. 시작하려면 애플리케이션의 horizon 구성 파일에서 silenced 구성 옵션에 작업의 클래스 이름을 추가하십시오:
'silenced' => [ App\Jobs\ProcessPodcast::class,],
또는, 무음 처리하려는 작업이 Laravel\Horizon\Contracts\Silenced 인터페이스를 구현할 수 있습니다. 작업이 이 인터페이스를 구현하는 경우 silenced 구성 배열에 없더라도 자동으로 무음 처리됩니다:
use Laravel\Horizon\Contracts\Silenced; class ProcessPodcast implements ShouldQueue, Silenced{ use Queueable; // ...}
Horizon 업그레이드
새로운 주요 버전의 Horizon으로 업그레이드할 때는 업그레이드 가이드를 주의 깊게 검토하는 것이 중요합니다.
Horizon 실행
애플리케이션의 config/horizon.php 구성 파일에서 감독자와 워커를 구성했으면 horizon Artisan 명령을 사용하여 Horizon을 시작할 수 있습니다. 이 단일 명령은 현재 환경에 대해 구성된 모든 워커 프로세스를 시작합니다:
php artisan horizon
Horizon 프로세스를 일시 중지하고 horizon:pause 및 horizon:continue Artisan 명령을 사용하여 작업을 계속 처리하도록 지시할 수 있습니다.
php artisan horizon:pause php artisan horizon:continue
또한 horizon:pause-supervisor 및 horizon:continue-supervisor Artisan 명령을 사용하여 특정 Horizon supervisor를 일시 중지하고 계속할 수도 있습니다.
php artisan horizon:pause-supervisor supervisor-1 php artisan horizon:continue-supervisor supervisor-1
horizon:status Artisan 명령을 사용하여 Horizon 프로세스의 현재 상태를 확인할 수 있습니다.
php artisan horizon:status
horizon:supervisor-status Artisan 명령을 사용하여 특정 Horizon supervisor의 현재 상태를 확인할 수 있습니다.
php artisan horizon:supervisor-status supervisor-1
horizon:terminate Artisan 명령을 사용하여 Horizon 프로세스를 정상적으로 종료할 수 있습니다. 현재 처리 중인 작업은 완료된 후 Horizon이 실행을 중지합니다.
php artisan horizon:terminate
Horizon 배포
애플리케이션의 실제 서버에 Horizon을 배포할 준비가 되면 php artisan horizon 명령을 모니터링하고 예기치 않게 종료될 경우 다시 시작하도록 프로세스 모니터를 구성해야 합니다. 걱정하지 마십시오. 아래에서 프로세스 모니터를 설치하는 방법을 논의하겠습니다.
애플리케이션 배포 프로세스 중에 Horizon 프로세스가 종료되도록 지시하여 프로세스 모니터에 의해 다시 시작되고 코드 변경 사항을 수신하도록 해야 합니다.
php artisan horizon:terminate
Supervisor 설치
Supervisor는 Linux 운영 체제용 프로세스 모니터이며, horizon 프로세스가 실행을 멈추면 자동으로 재시작합니다. Ubuntu에 Supervisor를 설치하려면 다음 명령어를 사용할 수 있습니다. Ubuntu를 사용하지 않는 경우, 운영 체제의 패키지 관리자를 사용하여 Supervisor를 설치할 수 있습니다.
sudo apt-get install supervisor
Supervisor를 직접 구성하는 것이 부담스럽게 느껴진다면, Laravel 프로젝트용으로 Supervisor를 자동으로 설치하고 구성해주는 Laravel Forge 사용을 고려해 보세요.
Supervisor 구성
Supervisor 구성 파일은 일반적으로 서버의 /etc/supervisor/conf.d 디렉토리에 저장됩니다. 이 디렉토리 내에서 Supervisor에게 프로세스 모니터링 방법을 지시하는 구성 파일을 원하는 만큼 생성할 수 있습니다. 예를 들어, horizon 프로세스를 시작하고 모니터링하는 horizon.conf 파일을 생성해 보겠습니다.
[program:horizon]process_name=%(program_name)scommand=php /home/forge/example.com/artisan horizonautostart=trueautorestart=trueuser=forgeredirect_stderr=truestdout_logfile=/home/forge/example.com/horizon.logstopwaitsecs=3600
Supervisor 설정을 정의할 때 stopwaitsecs 값이 가장 오래 실행되는 작업이 소요하는 시간(초)보다 커야 합니다. 그렇지 않으면 Supervisor가 작업이 완료되기 전에 작업을 강제로 종료할 수 있습니다.
위의 예시는 Ubuntu 기반 서버에서 유효하지만, Supervisor 구성 파일의 위치 및 파일 확장자는 다른 서버 운영 체제에 따라 다를 수 있습니다. 자세한 내용은 서버 문서를 참조하십시오.
Supervisor 시작하기
구성 파일이 생성되면 다음 명령을 사용하여 Supervisor 구성을 업데이트하고 모니터링되는 프로세스를 시작할 수 있습니다.
sudo supervisorctl reread sudo supervisorctl update sudo supervisorctl start horizon
Supervisor 실행에 대한 자세한 내용은 Supervisor 문서를 참조하십시오.
태그
Horizon을 사용하면 메일 발송 가능 항목, 브로드캐스트 이벤트, 알림 및 대기열에 있는 이벤트 리스너를 포함하여 작업에 "태그"를 할당할 수 있습니다. 실제로 Horizon은 작업에 연결된 Eloquent 모델에 따라 대부분의 작업에 지능적이고 자동으로 태그를 지정합니다. 예를 들어 다음 작업을 살펴보십시오.
<?php namespace App\Jobs; use App\Models\Video;use Illuminate\Contracts\Queue\ShouldQueue;use Illuminate\Foundation\Queue\Queueable; class RenderVideo implements ShouldQueue{ use Queueable; /** * 새 작업 인스턴스를 만듭니다. */ public function __construct( public Video $video, ) {} /** * 작업을 실행합니다. */ public function handle(): void { // ... }}
이 작업이 id 속성이 1인 App\Models\Video 인스턴스와 함께 대기열에 추가되면 자동으로 App\Models\Video:1 태그가 지정됩니다. 이는 Horizon이 작업의 속성에서 Eloquent 모델을 검색하기 때문입니다. Eloquent 모델이 발견되면 Horizon은 모델의 클래스 이름과 기본 키를 사용하여 작업에 지능적으로 태그를 지정합니다.
use App\Jobs\RenderVideo;use App\Models\Video; $video = Video::find(1); RenderVideo::dispatch($video);
수동으로 작업 태그 지정하기
대기열에 추가할 수 있는 객체 중 하나의 태그를 수동으로 정의하려면 클래스에서 tags 메서드를 정의할 수 있습니다.
class RenderVideo implements ShouldQueue{ /** * 작업에 할당해야 하는 태그를 가져옵니다. * * @return array<int, string> */ public function tags(): array { return ['render', 'video:'.$this->video->id]; }}
수동으로 이벤트 리스너 태그 지정하기
대기열에 추가된 이벤트 리스너의 태그를 검색할 때 Horizon은 자동으로 이벤트 인스턴스를 tags 메서드에 전달하여 이벤트 데이터를 태그에 추가할 수 있도록 합니다.
class SendRenderNotifications implements ShouldQueue{ /** * 리스너에 할당해야 하는 태그를 가져옵니다. * * @return array<int, string> */ public function tags(VideoRendered $event): array { return ['video:'.$event->video->id]; }}
알림
Horizon이 Slack 또는 SMS 알림을 보내도록 구성할 때, 관련 알림 채널의 필수 구성 요소를 검토해야 합니다.
대기열 중 하나에 대기 시간이 길 때 알림을 받으려면 Horizon::routeMailNotificationsTo, Horizon::routeSlackNotificationsTo, Horizon::routeSmsNotificationsTo 메서드를 사용할 수 있습니다. 애플리케이션의 App\Providers\HorizonServiceProvider의 boot 메서드에서 이러한 메서드를 호출할 수 있습니다.
/** * 애플리케이션 서비스를 부트스트랩합니다. */public function boot(): void{ parent::boot(); Horizon::routeSmsNotificationsTo('15556667777'); Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');}
알림 대기 시간 임계값 구성
애플리케이션의 config/horizon.php 구성 파일 내에서 "긴 대기"로 간주되는 시간(초)을 구성할 수 있습니다. 이 파일 내의 waits 구성 옵션을 사용하면 각 연결/대기열 조합에 대한 긴 대기 임계값을 제어할 수 있습니다. 정의되지 않은 연결/대기열 조합은 기본적으로 긴 대기 임계값이 60초로 설정됩니다.
'waits' => [ 'redis:critical' => 30, 'redis:default' => 60, 'redis:batch' => 120,],
메트릭
Horizon에는 작업 및 대기열 대기 시간 및 처리량에 대한 정보를 제공하는 메트릭 대시보드가 포함되어 있습니다. 이 대시보드를 채우려면 애플리케이션의 routes/console.php 파일에서 Horizon의 snapshot Artisan 명령을 5분마다 실행하도록 구성해야 합니다.
use Illuminate\Support\Facades\Schedule; Schedule::command('horizon:snapshot')->everyFiveMinutes();
실패한 작업 삭제
실패한 작업을 삭제하려면 horizon:forget 명령을 사용할 수 있습니다. horizon:forget 명령은 실패한 작업의 ID 또는 UUID를 유일한 인수로 허용합니다.
php artisan horizon:forget 5
실패한 모든 작업을 삭제하고 싶다면 horizon:forget 명령어에 --all 옵션을 제공하면 됩니다:
php artisan horizon:forget --all
큐에서 작업 지우기
애플리케이션의 기본 큐에서 모든 작업을 삭제하고 싶다면 horizon:clear Artisan 명령어를 사용하면 됩니다:
php artisan horizon:clear
특정 큐에서 작업을 삭제하려면 queue 옵션을 제공하면 됩니다:
php artisan horizon:clear --queue=emails