How to use Redis with Laravel

Foto door Emile Perron op Unsplash

PHP (Hypertext Preprocessor) is een open-source scripttaal die is ontworpen met ingebouwde mogelijkheden voor webontwikkeling. Het wordt al meer dan 20 jaar op grote schaal gebruikt voor webontwikkeling. Hoewel bijna 80% van de websites ermee werkt, heeft PHP een aantal belangrijke zwakke punten. Een daarvan is dat het single-threaded is.

PHP heeft geen standaardfunctie om extra threads te spawnen voor achtergrondprocessen. Vanwege het single-threaded ontwerp van de taal, zul je het moeilijk hebben om zelfs maar een eenvoudige webapplicatie te bouwen die e-mails moet versturen. Het verzenden van een e-mail is een duur en tijdrovend proces dat de enkele PHP thread kan blokkeren.

PHP frameworks pakken het probleem aan

PHP heeft een groot aantal open-source frameworks. Hun belangrijkste doel is om de ontwikkelingstijd voor complexe webapplicaties te verkorten door vooraf gedefinieerde concepten toe te passen. Ze helpen PHP ontwikkelaars om taken te automatiseren, efficiënt te werken met verschillende soorten databases, applicaties te beschermen tegen bekende kwetsbaarheden en testen uit te voeren. De populairste frameworks zijn Laravel, Zend, Symfony en Phalcon. Elk van hen heeft zijn eigen voordelen en een enorme gemeenschap die bijdraagt aan de open-source codebase.

Elk framework biedt een manier om het probleem van multi-threading in PHP te omzeilen. Als je een proces op de achtergrond wilt laten draaien, is het algemene concept als volgt: de informatie over een taak wordt naar een wachtrijdriver/berichtenbus gestuurd terwijl de server voortdurend de lijst met taken controleert om te zien of er iets is om uit te voeren.

Find your next developer

Aan de slag

Omgaan met berichtwachtrijen in Laravel

Laravel heeft een uniforme wachtrij-API waarmee je kunt kiezen uit verschillende technologieën zoals Redis, Amazon SQS, Beanstalkd of zelfs een ouderwets relationeel databasesysteem. Laten we eens kijken hoe Laravel werkt met Redis, een open-source in-memory opslag van gegevensstructuren.

Wat is het nut van Redis in Laravel? Conceptueel gezien push je een taak (of "dispatching a job", zoals het wordt genoemd in het Laravel ecosysteem) naar de Redis wachtrij waar het wacht tot het wordt opgehaald en verwerkt. Om wachtrijen te verwerken, heb je workers nodig die non-stop draaien. Op productieservers moet je een Supervisor hebben, een procesmonitor die vaak wordt gebruikt in Linux-omgevingen.

Laten we zeggen dat je een User model hebt, waarvan een instantie moet worden gemaakt voor elke nieuwe registratie. Er is geen standaard manier om dit te bereiken: het draait allemaal om voorkeuren. Om het eenvoudig te implementeren, heb je een observer en een taak in de wachtrij nodig:

De observer wordt getriggerd wanneer een instantie van het model wordt aangemaakt. De observer verzendt de opdracht naar de wachtrij.

De supervisor blijft queue:work uitvoeren voor het project. Zodra een nieuwe taak wordt verzonden, wordt deze verwerkt door de wachtrijwerker van Laravel.

Laten we eens kijken naar een codevoorbeeld.

Eerst moet je een observer maken voor het User-model en een job:

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

Vervolgens moet je wat je zojuist hebt gemaakt introduceren in de applicatie. Je kunt dit doen door een observer te registreren in de EventServiceProvider op de volgende manier:

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


Je applicatie heeft nu de definitie van wat te observeren en je moet het configureren om het werk te doen. De `UserObserver` moet reageren wanneer een instantie van het `User` model wordt gemaakt. Je kunt dat bereiken door de `created` methode van de observer voor het gerelateerde model bij te werken. Laten we een e-mail versturen 10 seconden nadat de instantie van het model is aangemaakt om te zien hoe het in de praktijk werkt.

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

Elke keer als een User wordt gemaakt, wordt de SendRegistrationEmail taak verzonden door de waarnemer.

``php namespace App\Jobs; class SendRegistrationEmail implements ShouldQue { 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('Welkom bij de applicatie!'); }); } }


Zo implementeer je de flow. Nu stuurt de applicatie een e-mail naar een nieuwe gebruiker na registratie.

Om het via wachtrijen te laten werken, moet je de configuraties bijwerken om de Redis driver te gebruiken. Nadat je Redis op je machine hebt geïnstalleerd, is het voldoende om eenmalig een update uit te voeren in `.env`: 

`QUEUE_CONNECTION=redis`

Vergeet daarna niet om je configuraties bij te werken: `php artisan config:cache`. Om Laravel's queue worker te starten, moet je `php artisan queue:work` uitvoeren.

## Problemen oplossen met Laravel's queue workers

Productieomgevingen vereisen dat de workers altijd actief zijn. Het `queue:work` commando zelf kan om veel redenen mislukken, zoals het overschrijden van de maximale time-out. Het handmatig controleren van de server om er zeker van te zijn dat de queue worker up is, is geen optie. In plaats daarvan gebruik je Supervisor, een procesmonitor voor Linux omgevingen.

Nadat je Supervisor op de server hebt geïnstalleerd, moet je het een configuratiebestand geven voor interactie met de wachtrijwerkers van Laravel. Laten we een `laravel-worker.conf` bestand maken dat het `queue:work` proces afhandelt.

``php
[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 deze configuratie moet je de Supervisor vertellen om de workers automatisch te herstarten en 4 parallelle processen te laten draaien. Laten we de processen starten:

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

Tot slot, dit is zo eenvoudig als je het leest. De Supervisor zal de werkers draaiende houden. Telkens wanneer de wachtrij een job krijgt, zullen de werkers deze oppikken en uitvoeren. Op deze manier zorg je ervoor dat de gebruiker niet hoeft te wachten totdat PHP de taak van het verzenden van een e-mail verwerkt en doorgaat naar de volgende pagina door deze tijdrovende taak naar 'parallelle' threads te verplaatsen.

Vind jouw volgende ontwikkelaar binnen enkele dagen, niet maanden

In een kort gesprek van 25 minuten:

  • gaan we in op wat je nodig hebt om je product te ontwikkelen;
  • Ons proces uitleggen om u te matchen met gekwalificeerde, doorgelichte ontwikkelaars uit ons netwerk
  • delen we de stappen met je om de juiste match te vinden, vaak al binnen een week.

Maak een afspraak