DEV Community

Dendi Handian
Dendi Handian

Posted on • Updated on

RabbitMQ Queue Driver for Laravel

Since version 6.0 LTS, Laravel has some available drivers for queue connection, such as database, Redis, Beanstalkd and AWS SQS. Those external services are great, but there will be a situation when you have to pick the right service for your app in a certain environment. For example, if your app is using AWS as the server then AWS SQS might be the best choice. Maybe there will be a situation when you have to pick another service that not supported (yet) by Laravel and it's the best for your environment and requirement, maybe it's RabbitMQ.

Laravel doesn't support RabbitMQ, but there is a package that enables it to be supported. Thanks to vyuldashev, laravel-queue-rabbitmq is an awesome package to make it happens. I'll show you.


Prerequisites

Of course, you have to set RabbitMQ ready on your machine. If you have no idea how to do it, then you can see my post about setting it up in Laradock here. And for the demo, I will use the simple mail sending example using artisan command that I have practiced here.


Installing laravel-queue-rabbitmq package

There is a comment from Francis Igbokwe about the recent version issue. You may want to inspect the comment section below first.

By using composer and go to your project directory using CLI, execute this command:

composer require vladimir-yuldashev/laravel-queue-rabbitmq
Enter fullscreen mode Exit fullscreen mode

Wait until the installation is done.

Installing AMQP support package

I will give explanation about AMQP later (maybe), but in order to be work between PHP and rabbitmq, you must install the any available AMQP support package. I have tried AmqpBunny package and it works. So to install the package, execute this command:

composer require enqueue/amqp-bunny:^0.8
Enter fullscreen mode Exit fullscreen mode

Wait until the installation is done.

Configure the queue connection

see Daniel Ozeh's comment for environment setting issue for the recent version.

In your laravel app's config/queue.php file, add the new configuration item for rabbitmq inside the connections array:

config/queue.php:

...

'connections' => [

        ...

        'rabbitmq' => [

            'driver' => 'rabbitmq',

            /*
         * Set to "horizon" if you wish to use Laravel Horizon.
         */
            'worker' => env('RABBITMQ_WORKER', 'default'),

            'dsn' => env('RABBITMQ_DSN', null),

            /*
         * Could be one a class that implements \Interop\Amqp\AmqpConnectionFactory for example:
         *  - \EnqueueAmqpExt\AmqpConnectionFactory if you install enqueue/amqp-ext
         *  - \EnqueueAmqpLib\AmqpConnectionFactory if you install enqueue/amqp-lib
         *  - \EnqueueAmqpBunny\AmqpConnectionFactory if you install enqueue/amqp-bunny
         */

            'factory_class' => \Enqueue\AmqpBunny\AmqpConnectionFactory::class,

            'host' => env('RABBITMQ_HOST', '127.0.0.1'),
            'port' => env('RABBITMQ_PORT', 5672),

            'vhost' => env('RABBITMQ_VHOST', '/'),
            'login' => env('RABBITMQ_LOGIN', 'guest'),
            'password' => env('RABBITMQ_PASSWORD', 'guest'),

            'queue' => env('RABBITMQ_QUEUE', 'default'),

            'options' => [

                'exchange' => [

                    'name' => env('RABBITMQ_EXCHANGE_NAME'),

                    /*
                 * Determine if exchange should be created if it does not exist.
                 */

                    'declare' => env('RABBITMQ_EXCHANGE_DECLARE', true),

                    /*
                 * Read more about possible values at https://www.rabbitmq.com/tutorials/amqp-concepts.html
                 */

                    'type' => env('RABBITMQ_EXCHANGE_TYPE', \Interop\Amqp\AmqpTopic::TYPE_DIRECT),
                    'passive' => env('RABBITMQ_EXCHANGE_PASSIVE', false),
                    'durable' => env('RABBITMQ_EXCHANGE_DURABLE', true),
                    'auto_delete' => env('RABBITMQ_EXCHANGE_AUTODELETE', false),
                    'arguments' => env('RABBITMQ_EXCHANGE_ARGUMENTS'),
                ],

                'queue' => [

                    /*
                 * Determine if queue should be created if it does not exist.
                 */

                    'declare' => env('RABBITMQ_QUEUE_DECLARE', true),

                    /*
                 * Determine if queue should be binded to the exchange created.
                 */

                    'bind' => env('RABBITMQ_QUEUE_DECLARE_BIND', true),

                    /*
                 * Read more about possible values at https://www.rabbitmq.com/tutorials/amqp-concepts.html
                 */

                    'passive' => env('RABBITMQ_QUEUE_PASSIVE', false),
                    'durable' => env('RABBITMQ_QUEUE_DURABLE', true),
                    'exclusive' => env('RABBITMQ_QUEUE_EXCLUSIVE', false),
                    'auto_delete' => env('RABBITMQ_QUEUE_AUTODELETE', false),
                    'arguments' => env('RABBITMQ_QUEUE_ARGUMENTS'),
                ],
            ],

            /*
         * Determine the number of seconds to sleep if there's an error communicating with rabbitmq
         * If set to false, it'll throw an exception rather than doing the sleep for X seconds.
         */

            'sleep_on_error' => env('RABBITMQ_ERROR_SLEEP', 5),

            /*
         * Optional SSL params if an SSL connection is used
         * Using an SSL connection will also require to configure your RabbitMQ to enable SSL. More details can be founds here: https://www.rabbitmq.com/ssl.html
         */

            'ssl_params' => [
                'ssl_on' => env('RABBITMQ_SSL', false),
                '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),
            ],
        ],
    ],

...
Enter fullscreen mode Exit fullscreen mode

And in your laravel app's .env file, set parameters into like this:

QUEUE_CONNECTION=rabbitmq

RABBITMQ_HOST=rabbitmq
RABBITMQ_PORT=5672
RABBITMQ_VHOST=/
RABBITMQ_LOGIN=guest
RABBITMQ_PASSWORD=guest
RABBITMQ_QUEUE=default

RABBITMQ_EXCHANGE_NAME=default
RABBITMQ_EXCHANGE_DECLARE=
RABBITMQ_EXCHANGE_TYPE=
RABBITMQ_EXCHANGE_PASSIVE=
RABBITMQ_EXCHANGE_DURABLE=
RABBITMQ_EXCHANGE_AUTODELETE=
RABBITMQ_EXCHANGE_ARGUMENTS=default

RABBITMQ_QUEUE_DECLARE=
RABBITMQ_QUEUE_DECLARE_BIND=
RABBITMQ_QUEUE_PASSIVE=
RABBITMQ_QUEUE_DURABLE=
RABBITMQ_QUEUE_EXCLUSIVE=
RABBITMQ_QUEUE_AUTODELETE=
RABBITMQ_QUEUE_ARGUMENTS=default

RABBITMQ_ERROR_SLEEP=5

RABBITMQ_SSL=
RABBITMQ_SSL_CAFILE=
RABBITMQ_SSL_LOCALCERT=
RABBITMQ_SSL_LOCALKEY=
RABBITMQ_SSL_VERIFY_PEER=
RABBITMQ_SSL_PASSPHRASE=
Enter fullscreen mode Exit fullscreen mode

RabbitMQ connection test and demo

You can check the rabbitmq management first to make sure the Queues still empty and maybe stop the php-worker first if you use it to see the stored queue job later before it executed automatically.

We will use an artisan command to send an email as I practiced before while demonstrating mailhog or php-worker. So, enter the project directory using CLI if you haven't and execute the artisan command:

php artisan example:send-mail
Enter fullscreen mode Exit fullscreen mode

If you managed to disable the php-worker before, you should see the queue has 1 job ready to be executed:

2020-04-01-00h30-25

Then start the worker to see if it's working for real.


Have fun experimenting RabbitMQ with Laravel!


versions used:
 - laravel: 6.0 LTS
 - rabbitmq: 3.8.1
 - laravel-queue-rabbitmq: ^10.0
 - enqueue/amqp-bunny: ^0.8
Enter fullscreen mode Exit fullscreen mode

Top comments (4)

Collapse
 
laurence702 profile image
Francis Igbokwe

Nice read. please update post to say to optionally install enqueue/amqp-bunny first because trying to install the rabbitMq driver first may give composer dependency errors as the one I've just showed in the image attached.

Collapse
 
dendihandian profile image
Dendi Handian

Added. I haven't try the new version yet, so I just pointed out to this comment

Collapse
 
danielozeh profile image
Daniel Ozeh

Nice. RABBITMQ_LOGIN in the .env and causes a "ACCESS_REFUSED - Login was refused using authentication mechanism AMQPLAIN. For details see the broker logfile.(0, 0)" error

you should probably update to RABBITMQ_USER

Collapse
 
dendihandian profile image
Dendi Handian

I have pointed a note in the article to this comment. Thanks for your feedback.