A Laravel rendelkezik a WebSocket protokoll egy ideális megvalósítási lehetőségével: segítségével könnyű információkat szolgáltatni a felhasználók számára és kommunikációt folytatni az ügyfelek között. Egyszerűen írhatunk egy jó, valós idejű webalkalmazást ezekkel a funkciókkal. Nézzük is meg, hogyan!
A probléma
A WebSocket protokoll alapvetően full-duplex kommunikációs csatornákon alapul. A Laravel csak a szervertől a kliensig történő üzenetküldést valósítja meg, tehát a WebSocket szerveren keresztül nincs mód az adatok kliens oldalról való továbbítására. Azonban fontos megemlíteni, hogy ez a sajátosság biztonságosabbá teszi a keretrendszert: ha a kliens oldalon írt kód nem megfelelő, biztonsági és szerver-terheltségi problémák merülhetnek fel. Éppen ezért nagyon óvatosnak kell lennünk, amikor az kliens-szerver adatátvitelen dolgozunk.
Amink van
Az információk továbbításakor az adatokat egy Redis csatornán teszik közzé. Erre feliratkozik a Socket szerver és folyamatosan figyeli a változásokat. Ha valami történik, a Socker szerver elküldi az adatokat a kliens oldalra.
A koncepció
Első ránézésre úgy tűnhet, hogy a Laravel csak a szerver-kliens kommunikációt támogatja, ám ez csak félig igaz! Létezik egy whispering funkció, ami a kliensek közötti üzenetküldésre használható. A Socket szerver feldolgozza az adatokat és elküldi a másik kliensnek, aki szintén csatlakozott a csatornához.
Ezt a funkciót felhasználhatjuk és ki is bővíthetjük saját megoldásokkal. Amikor a Socket szerver kiadja az adatokat az kliensek számára, akkor közzéteszi a Redis csatornán is. Később egy konzolos parancsot írunk, amely az adott csatornára csatlakozik és megfelelően feldolgozza az üzenetet.
Az implementáció
A megvalósításhoz a Laravel Echo & Redis & Laravel-Echo-Server triót fogjuk használni. Annak ellenére, hogy a Laravel-Echo-Server forkját is igénybe vesszük - ami képes adatokat publikálni a Redis csatornán -, az Echo whispering metódus használatakor a Socket Server nem csak továbbítani fogja az üzenetet a többi kliensnek, hanem közzé is teszi az adatokat az adott Redis csatornán (ugyanazon, amit a rendszer olvas).
Miután letöltöttük és konfiguráltuk a szervert, indítsuk el:
node bin/server.js start
A kliens oldalon bevetjük a whispering metódust:
Echo.join('orderTable.' + orderId).whisper(
'OrderUpdated',
{
message: 'This message will be available from the server.'
}
);
Ne feledjük: a csatornának presence vagy privát csatornának kell lennie, hogy használni tudjuk a whispering funkciót. Ezt követően meg kell írnunk a parancsot, ami hozzáfér a mi csatornánkhoz. Először is készítsük el az osztályt:
php artisan make:command RedisSubscriber
Módosítsuk a parancs megnevezését valami másra:
protected $signature = 'redis:subscribe';
A Laravel dokumentációja szerint fel lehet iratkozni a csatornákra helyettesítő karakterek (wildcard) használatával. Ez hasznunkra válik ebben a helyzetben, mert a Laravel és a Socket szerver előtagokat használ a csatorna nevében. Ez segíti a jobb elkülönítést és azonosítást, amikor több alkalmazás használja ugyanazt a Redis szervert. Emellett (az alkalmazás üzleti logikája alapján) postfixekkel is elválasztjuk csatornáinkat egymástól. Ezen információk ismeretében a handle() metódusban feliratkozunk a csatornára:
Redis::psubscribe(['*orderTable.*'], function ($message, $channel) {
// do something
});
Ha egy idő után futtatjuk a parancsot, ez a hibaüzenetet kaphatjuk:
read error on connection to 127.0.0.1:6379
Ezt a hibát a PHP 60 másodperccel a Redis szerverrel való kapcsolat megszakítása után dobja ki. Manuálisan módosíthatjuk az alapértelmezett időt:
ini_set("default_socket_timeout", -1); //-1 is not set
Végül így kell kinéznie Redis Subscriber-nek:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Redis;
class RedisSubscriber extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'redis:subscribe';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
ini_set("default_socket_timeout", -1);
Redis::psubscribe(['*orderTable.*'], function ($message, $channel) {
echo $channel;
echo PHP_EOL;
echo $message;
echo PHP_EOL;
});
}
}
Reméljük, tudtunk iránymutatással szolgálni a Laravel Echo útvesztőjében. Hasonló tartalmakért olvasd el további blogbejegyzéseinket!
Az eredeti (angol nyelvű) cikk elérhető itt. Fordította: Kádár Kyra