Ce contenu n'est pas disponible en votre langue. Voici la version en suédois.

Using Redis with Laravel: PHP message queuing example

May 14, 2021 · 5 mins de lecture

PHP (Hypertext Preprocessor) is an open-source scripting language that was designed with built-in web development capabilities. It has been used widely in web development for over 20 years. Even though it currently powers almost 80% of websites, PHP has some substantial weaknesses. Being single-threaded is one of them.

PHP doesn’t have a default feature to spawn additional threads for background processes. Because of the single-threaded design of the language, you’ll have a hard time building even a simple web application that has to send emails. Sending an email is an expensive and time-consuming process that can block the PHP single thread.

PHP frameworks address the problem

PHP has a great number of open-source frameworks. Their main goal is to decrease the development time for complex web applications by applying pre-defined concepts. They help PHP developers to automate tasks, work efficiently with different types of databases, protect applications against well-known vulnerabilities, and perform testing. The most popular frameworks are Laravel, Zend Framework, Symfony, and Phalcon. Each one of them has its own benefits and a huge community contributing to the open-source codebase.

Every framework offers a way around the problem of multi-threading in PHP. If you want to have a process running in the background, the general concept is the following: the information about a task is sent to a queue driver/message bus while the server is constantly checking the list of tasks to see if there is something to execute.

Handling message queues in Laravel

Laravel has a unified queueing API that lets you choose from various technologies such as Redis, Amazon SQS, Beanstalkd, or even an old-fashioned relational database system. Let’s look at how Laravel works with Redis, an open-source in-memory data structure storage.

What’s the use of Redis in Laravel? Conceptually, you’re pushing a task (or “dispatching a job”, as it’s called in the Laravel ecosystem) to the Redis queue where it waits until being picked and processed. To process queues, you need to have workers that run non-stop. On production servers, you should have a Supervisor, a process monitor commonly used in Linux environments.

Let’s say you have a User model, an instance of which should be created for every new registration. There is no default way of achieving this: it’s all about preferences. To implement it simply, you’ll need an observer and a queued job:

The observer gets triggered when an instance of the model is created. The observer dispatches the job to the queue. The Supervisor keeps running queue:work for the project. As soon as a new job is dispatched, it will be processed by Laravel’s queue worker.

Let’s look at a code example.

First, you need to create an observer for the User model and a job:

php artisan make:observer UserObserver --model=User
php artisan make:job SendRegistrationEmail

Next, you need to introduce what you have just created to the application. You can do it by registering an observer in the EventServiceProvider as following:

namespace App\Providers;
class EventServiceProvider extends ServiceProvider 
{
public function boot()
{
User::observe(UserObserver::class);
    	}
}

Your application now has the definition of what to observe, and you should configure it to do the job. UserObserver needs to react when an instance of the User model is created. You can achieve that by updating the created method of the observer for the related model. Let’s make it send an email 10 seconds after the model instance is created to see how it works in practice.

namespace App\Observers;
class UserObserver
{
public function created(User $user)
{
SendRegistrationEmail::dispatch($user->email)->delay(now()->addSeconds(10));
}
}

Every time a User is created, SendRegistrationEmail job will be dispatched by the observer.

namespace App\Jobs;
class SendRegistrationEmail implements ShouldQueue
{
	public $email;
	public function __construct($email)
{
$this->email = $email;
}
public function handle()
{
	$email = $this->email;
Mail::send([], [], function ($message) use ($email) 
{ 
$message
->to($email)
->subject('Hello, world!')
->setBody('Welcome to the application!');
});
}
}

This is how you implement the flow. Now the application sends an email to a new user upon registration.

To make it work via queues, you need to update configurations to use the Redis driver. After installing Redis on your machine, it’s enough to update in .env once:

QUEUE_CONNECTION=redis

Afterward, don’t forget to update your configurations: php artisan config:cache. To start Laravel’s queue worker, you need to run php artisan queue:work.

Solving issues with Laravel’s queue workers

Production environments require you to have the workers running all the time. queue:work command itself can fail due to many reasons, such as exceeding the maximum timeout. Checking the server manually to make sure if the queue worker is up is not an option. Instead, you’ll use Supervisor, a process monitor for Linux environments.

After installing the Supervisor on the server, you need to give it a configuration file to interact with Laravel’s queue workers. Let’s create a laravel-worker.conf file that handles the queue:work process.

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /home/project/artisan queue:work --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=root
numprocs=4
redirect_stderr=true
stdout_logfile=/home/project/logs/worker.log
stopwaitsecs=3600

In this configuration, you should tell the Supervisor to restart the workers automatically and have 4 parallel processes running. Let’s start the processes:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*

That’s it. The Supervisor will keep the workers running. Whenever the queue gets a job, the workers will pick and run it. This way, you ensure the user doesn’t have to wait until PHP processes the task of sending an email and proceeds to the next page by moving this time-consuming job to ‘parallel’ threads.

Contenu

Le recrutement sans stress d'experts en technologie commence ici

Le codage est un langage universel. C'est pourquoi Proxify recherche les meilleurs talents en technologie partout dans le monde. Le recrutement de votre prochain développeur sans un serveur est sûr, sécurisé et simple grâce à nous. Et aussi très bon marché, bien sûr.

Lors d'un court appel de 15 minutes, nous aimerions :

  • Comprendre le genre de talent dont a besoin votre entreprise
  • Discuter le plan qui vous convient le mieux
  • Expliquer le fonctionnement de Proxify

Programmer une réunion