Laravel Queue Rabbitmq
vladimir-yuldashev/laravel-queue-rabbitmq
Laravel 큐용 RabbitMQ 드라이버입니다. Laravel Horizon을 지원합니다.
Laravel용 RabbitMQ 큐 드라이버
지원 정책
새 기능은 최신 버전에만 추가됩니다. 버그 수정은 다음 정책에 따라 제공됩니다:
| 패키지 버전 | Laravel 버전 | 버그 수정 제공 기한 | |
|---|---|---|---|
| 13 | 9 | 2023년 8월 8일 | 문서 |
설치
다음 Composer 명령으로 패키지를 설치할 수 있습니다:
composer require vladimir-yuldashev/laravel-queue-rabbitmq
패키지는 자동으로 등록됩니다.
설정
config/queue.php에 연결 설정을 추가하세요:
다음은 RabbitMQ 연결과 드라이버가 동작하는 데 필요한 최소 설정입니다.
'connections' => [
// ...
'rabbitmq' => [
'driver' => 'rabbitmq',
'hosts' => [
[
'host' => env('RABBITMQ_HOST', '127.0.0.1'),
'port' => env('RABBITMQ_PORT', 5672),
'user' => env('RABBITMQ_USER', 'guest'),
'password' => env('RABBITMQ_PASSWORD', 'guest'),
'vhost' => env('RABBITMQ_VHOST', '/'),
],
// ...
],
// ...
],
// ...
],선택적 큐 설정
필요하면 연결 설정에 큐 옵션을 추가할 수 있습니다. 이 연결에서 생성하는 모든 큐에 해당 속성이 적용됩니다.
지연된 메시지에 우선순위를 적용하려면 추가 옵션을 설정하세요.
- 최대 우선순위를 생략하면 이 기능을 사용할 때 최대 우선순위가 2로 설정됩니다.
'connections' => [
// ...
'rabbitmq' => [
// ...
'options' => [
'queue' => [
// ...
'prioritize_delayed' => false,
'queue_max_priority' => 10,
],
],
],
// ...
],라우팅 키를 사용해 exchange에 메시지를 발행하려면 추가 옵션을 설정하세요.
- exchange를 생략하면 RabbitMQ는 해당 라우팅 키에
amq.directexchange를 사용합니다. - 라우팅 키를 생략하면 기본값으로
queue이름을 사용합니다. - 라우팅 키의
%s는 큐 이름으로 치환됩니다.
참고: 라우팅 키가 있는 exchange를 사용한다면 큐와 바인딩을 직접 생성해야 할 수 있습니다.
'connections' => [
// ...
'rabbitmq' => [
// ...
'options' => [
'queue' => [
// ...
'exchange' => 'application-x',
'exchange_type' => 'topic',
'exchange_routing_key' => '',
],
],
],
// ...
],Laravel은 실패한 Job을 데이터베이스에 저장합니다. 이와 별도로 다른 프로세스가 해당 메시지를 처리하도록 해야 할 수도 있습니다. RabbitMQ에서 실패한 메시지를 exchange나 특정 큐로 다시 라우팅하려면 추가 옵션을 설정하세요.
- exchange를 생략하면 RabbitMQ는 해당 라우팅 키에
amq.directexchange를 사용합니다. - 라우팅 키를 생략하면 기본값으로 큐 이름에
.failed를 붙인 값을 사용합니다. - 라우팅 키의
%s는 큐 이름으로 치환됩니다.
참고: 실패한 Job용 exchange와 라우팅 키를 사용한다면 exchange, 큐, 바인딩을 직접 생성해야 할 수 있습니다.
'connections' => [
// ...
'rabbitmq' => [
// ...
'options' => [
'queue' => [
// ...
'reroute_failed' => true,
'failed_exchange' => 'failed-exchange',
'failed_routing_key' => 'application-x.%s',
],
],
],
// ...
],Horizon 지원
이 패키지는 8.0부터 Laravel Horizon을 기본 지원합니다. 먼저 Horizon을 설치한 다음 RABBITMQ_WORKER를 horizon으로 설정하세요.
Horizon은 워커가 디스패치하는 이벤트에 의존합니다. 이 이벤트는 메시지와 Job에 어떤 처리가 이루어졌는지 Horizon에 알려 줍니다.
이 라이브러리는 Horizon을 지원하지만, Laravel이 Horizon 호환 QueueApi를 사용하도록 설정해야 합니다.
'connections' => [
// ...
'rabbitmq' => [
// ...
/* Set to "horizon" if you wish to use Laravel Horizon. */
'worker' => env('RABBITMQ_WORKER', 'default'),
],
// ...
],사용자 정의 RabbitMQJob 클래스 사용
다른 애플리케이션이 발행한 메시지를 처리해야 할 때가 있습니다.
이 메시지는 Laravel의 Job 페이로드 형식을 따르지 않을 수 있습니다.
그 경우 Laravel 워커는 실제로 실행할 Job이나 클래스를 판단할 수 없습니다.
내장 RabbitMQJob::class를 상속하고 큐 연결 설정에 사용자 정의 클래스를 지정할 수 있습니다.
설정의 job 키에 해당 클래스 이름을 지정하면 브로커에서 가져오는 모든 메시지를 이 클래스로 감쌉니다.
설정 예제:
'connections' => [
// ...
'rabbitmq' => [
// ...
'options' => [
'queue' => [
// ...
'job' => \App\Queue\Jobs\RabbitMQJob::class,
],
],
],
// ...
],사용자 정의 Job 클래스 예제:
<?php
namespace App\Queue\Jobs;
use VladimirYuldashev\LaravelQueueRabbitMQ\Queue\Jobs\RabbitMQJob as BaseJob;
class RabbitMQJob extends BaseJob
{
/**
* Fire the job.
*
* @return void
*/
public function fire()
{
$payload = $this->payload();
$class = WhatheverClassNameToExecute::class;
$method = 'handle';
($this->instance = $this->resolve($class))->{$method}($this, $payload);
$this->delete();
}
}
페이로드에 추가 속성을 넣으려면 다음과 같이 작성할 수 있습니다:
<?php
namespace App\Queue\Jobs;
use VladimirYuldashev\LaravelQueueRabbitMQ\Queue\Jobs\RabbitMQJob as BaseJob;
class RabbitMQJob extends BaseJob
{
/**
* Get the decoded body of the job.
*
* @return array
*/
public function payload()
{
return [
'job' => 'WhatheverFullyQualifiedClassNameToExecute@handle',
'data' => json_decode($this->getRawBody(), true)
];
}
}JSON 형식이 아닌 원시 메시지나 JSON에 job 키가 없는 메시지를 처리하려면 getName 메서드의 스텁을 추가해야 합니다:
<?php
namespace App\Queue\Jobs;
use Illuminate\Support\Facades\Log;
use VladimirYuldashev\LaravelQueueRabbitMQ\Queue\Jobs\RabbitMQJob as BaseJob;
class RabbitMQJob extends BaseJob
{
public function fire()
{
$anyMessage = $this->getRawBody();
Log::info($anyMessage);
$this->delete();
}
public function getName()
{
return '';
}
}사용자 정의 연결 사용
내장 PhpAmqpLib\Connection\AMQPStreamConnection::class 또는 PhpAmqpLib\Connection\AMQPSLLConnection::class를 상속하고 연결 설정에 사용자 정의 클래스를 지정할 수 있습니다.
설정의 connection 키에 해당 클래스 이름을 지정하면 모든 연결이 이 클래스를 사용합니다.
설정 예제:
'connections' => [
// ...
'rabbitmq' => [
// ...
'connection' = > \App\Queue\Connection\MyRabbitMQConnection::class,
],
// ...
],사용자 정의 워커 클래스 사용
VladimirYuldashev\LaravelQueueRabbitMQ\Queue\RabbitMQQueue를 상속하면 사용자 정의 RabbitMQQueue::class를 사용할 수 있습니다.
RABBITMQ_WORKER를 \App\Queue\RabbitMQQueue::class로 설정해 Laravel이 해당 클래스를 사용하도록 지정하세요.
참고: 워커 클래스는 반드시
VladimirYuldashev\LaravelQueueRabbitMQ\Queue\RabbitMQQueue를 상속해야 합니다.
'connections' => [
// ...
'rabbitmq' => [
// ...
/* Set to a class if you wish to use your own. */
'worker' => \App\Queue\RabbitMQQueue::class,
],
// ...
],<?php
namespace App\Queue;
use VladimirYuldashev\LaravelQueueRabbitMQ\Queue\RabbitMQQueue as BaseRabbitMQQueue;
class RabbitMQQueue extends BaseRabbitMQQueue
{
// ...
}예제: 재연결 구현
연결이 끊어졌을 때 RabbitMQ에 다시 연결하려면 메시지 발행 메서드와 createChannel 메서드를 재정의할 수 있습니다.
참고: 다음 코드는 권장 구현 방식이 아니라 설명용 예제입니다.
<?php
namespace App\Queue;
use PhpAmqpLib\Exception\AMQPChannelClosedException;
use PhpAmqpLib\Exception\AMQPConnectionClosedException;
use VladimirYuldashev\LaravelQueueRabbitMQ\Queue\RabbitMQQueue as BaseRabbitMQQueue;
class RabbitMQQueue extends BaseRabbitMQQueue
{
protected function publishBasic($msg, $exchange = '', $destination = '', $mandatory = false, $immediate = false, $ticket = null): void
{
try {
parent::publishBasic($msg, $exchange, $destination, $mandatory, $immediate, $ticket);
} catch (AMQPConnectionClosedException|AMQPChannelClosedException) {
$this->reconnect();
parent::publishBasic($msg, $exchange, $destination, $mandatory, $immediate, $ticket);
}
}
protected function publishBatch($jobs, $data = '', $queue = null): void
{
try {
parent::publishBatch($jobs, $data, $queue);
} catch (AMQPConnectionClosedException|AMQPChannelClosedException) {
$this->reconnect();
parent::publishBatch($jobs, $data, $queue);
}
}
protected function createChannel(): AMQPChannel
{
try {
return parent::createChannel();
} catch (AMQPConnectionClosedException) {
$this->reconnect();
return parent::createChannel();
}
}
}기본 큐
Laravel이 큐를 지정하지 않으면 연결은 이름이 default인 기본 큐를 사용합니다.
연결 설정에 매개변수를 추가해 기본 큐를 변경할 수 있습니다.
'connections' => [
// ...
'rabbitmq' => [
// ...
'queue' => env('RABBITMQ_QUEUE', 'default'),
],
// ...
],하트비트
연결의 하트비트 설정 기본값은 0입니다.
다음과 같이 설정을 변경할 수 있습니다.
'connections' => [
// ...
'rabbitmq' => [
// ...
'options' => [
// ...
'heartbeat' => 10,
],
],
// ...
],SSL 보안 연결
RabbitMQ 서버에 보안 연결을 사용하려면 다음 옵션을 추가해야 합니다.
'connections' => [
// ...
'rabbitmq' => [
// ...
'secure' = > true,
'options' => [
// ...
'ssl_options' => [
'cafile' => env('RABBITMQ_SSL_CAFILE', null),
'local_cert' => env('RABBITMQ_SSL_LOCALCERT', null),
'local_key' => env('RABBITMQ_SSL_LOCALKEY', null),
'verify_peer' => env('RABBITMQ_SSL_VERIFY_PEER', true),
'passphrase' => env('RABBITMQ_SSL_PASSPHRASE', null),
],
],
],
// ...
],데이터베이스 커밋 이후 이벤트
모든 데이터베이스 커밋이 완료된 뒤 Laravel 워커가 이벤트를 디스패치하도록 하려면 다음과 같이 설정하세요.
'connections' => [
// ...
'rabbitmq' => [
// ...
'after_commit' => true,
],
// ...
],지연 연결
기본적으로 연결은 지연 연결로 생성됩니다. 지연 연결을 사용하지 않으려면 다음 설정으로 끌 수 있습니다.
'connections' => [
// ...
'rabbitmq' => [
// ...
'lazy' = > false,
],
// ...
],네트워크 프로토콜
연결에 사용하는 기본 네트워크 프로토콜은 tcp입니다.
다른 프로토콜을 사용하려면 설정에 값을 추가하세요.
사용 가능한 프로토콜: tcp, ssl, tls
'connections' => [
// ...
'rabbitmq' => [
// ...
'network_protocol' => 'tcp',
],
// ...
],네트워크 타임아웃
옵션 매개변수로 네트워크 타임아웃을 설정할 수 있습니다. 모든 실수 값의 단위는 초이며, 0은 무제한 타임아웃을 의미할 수 있습니다. 다음 예제는 기본값을 보여 줍니다.
'connections' => [
// ...
'rabbitmq' => [
// ...
'options' => [
// ...
'connection_timeout' => 3.0,
'read_timeout' => 3.0,
'write_timeout' => 3.0,
'channel_rpc_timeout' => 0.0,
],
],
// ...
],Octane 지원
이 패키지는 13.3.0부터 Laravel Octane을 기본 지원합니다.
먼저 Octane을 설치하고 Octane 설정에서 rabbitmq 연결을 미리 준비(warm)하도록 설정하세요.
참고: https://github.com/vyuldashev/laravel-queue-rabbitmq/issues/460#issuecomment-1469851667
Laravel에서 사용
설정을 마치면 Laravel Queue API를 사용할 수 있습니다. 다른 큐 드라이버를 사용해 왔다면 추가로 변경할 필요가 없습니다. Queue API 사용법은 Laravel 공식 문서를 참고하세요: http://laravel.com/docs/queues
Lumen에서 사용
Lumen에서는 bootstrap/app.php에 다음과 같이 서비스 프로바이더를 수동으로 등록해야 합니다:
$app->register(VladimirYuldashev\LaravelQueueRabbitMQ\LaravelQueueRabbitMQServiceProvider::class);메시지 소비
메시지를 소비하는 방법은 두 가지입니다.
-
Laravel 내장 명령인
queue:work는basic_get을 사용합니다. 여러 큐를 소비하려면 이 명령을 사용하세요. -
패키지가 제공하는
rabbitmq:consume명령은basic_consume을 사용합니다. 원문은basic_get보다 성능이 약 2배 높다고 설명하지만, 여러 큐는 지원하지 않습니다.
테스트
docker-compose로 RabbitMQ를 준비하세요:
docker compose up -d다음 명령으로 테스트 모음을 실행할 수 있습니다:
# To run both style and unit tests.composer test# To run only style tests.composer test:style# To run only unit tests.composer test:unit스타일 테스트에서 오류가 발생하면 다음 명령으로 대부분의 문제를 자동 수정할 수 있습니다:
composer fix:style기여
버그를 찾고 이슈를 등록해 이 패키지에 기여할 수 있습니다. 풀 리퀘스트나 이슈를 작성할 때 대상 패키지 버전을 표시해 주세요. (예: [5.2] Fatal error on delayed job)