# TrueAsync v Laravelu: architektura skutečné konkurence bez Swoole
Tradiční řešení pro asynchronnost v PHP, jako Swoole nebo RoadRunner, vyžadují hlubokou modifikaci kódu a zavedení barevných funkcí. TrueAsync nabízí zásadně jiný přístup — modifikaci jádra Zend pro průhlednou asynchronnost. Probereme, jak přizpůsobit Laravel tomuto modelu, překonat problémy stateful služeb a zajistit konkurenční zpracování operací vázaných na I/O.
Základy TrueAsync: jak funguje průhledná asynchronnost
TrueAsync je alternativní jádro PHP, které modifikuje Zend Engine, I/O knihovny a práci s DB. Jeho klíčová výhoda spočívá v absenci problému barevných funkcí. Na rozdíl od Node.js nebo Python asyncio běžné funkce PHP (PDO::query(), file_get_contents()) automaticky předají řízení plánovači v okamžiku čekání na I/O. Korutiny se pozastavují na úrovni C funkcí, což umožňuje zpracovávat stovky požadavků v jednom vlákně.
Důležité je pochopit: nejde o vícevláknovost. Model je založen na cooperative multitasking — přepínání kontextů při čekání na externí zdroje. Pro úlohy vázané na CPU (náročné výpočty) není efektivní, ale ideální pro typické webové scénáře s dotazy k DB a API. Příklad základního použití:
use function Async\spawn;
use function Async\await;
use function Async\delay;
$a = spawn(function() {
delay(100);
return 'result A';
});
$b = spawn(function() {
delay(100);
return 'result B';
});
// Obecný čas provedení ~100 ms
// Celkový čas provedení ~100 ms
echo await($a);
echo await($b);
Problém stateful služeb v Laravelu
Laravel byl původně navržen pro model FPM, kde se každý požadavek zpracovává v izolovaném procesu. Stateful služby (AuthManager, Session, Router) ukládají stav do vlastností objektů, které se po zpracování požadavku zničí. V async režimu proces běží neustále, což vede k únikům stavu:
// Korutina A: požadavek od user_1
Auth::loginUsingId(1);
delay(200);
// Korutina B: požadavek od user_2
Auth::loginUsingId(2);
// Návrat do korutiny A
echo Auth::id(); // Vrátí 2 místo 1
Statické vlastnosti (Model::$dispatcher, Facade::$resolvedInstance) a služby v IoC kontejneru se stávají společnými pro všechny požadavky. Octane tento problém řeší klonováním kontejneru, ale to přináší režii a neřeší statické vlastnosti.
Kontextová izolace: architektura řešení
TrueAsync poskytuje current_context() — úložiště dat vázané na životní cyklus požadavku. Při ukončení korutiny se kontext automaticky vyčistí. Architektura dělí Laravel na dvě zóny:
- Statické jádro: router, konfigurace, IoC kontejner. Načte se jednou, společné pro všechny požadavky.
- Služby na požadavek: Auth, Session, Cookie. Vytvářejí se v kontextu každé korutiny.
Klíčový mechanismus — zachycení resolvinu služeb přes AsyncApplication::resolve():
protected function resolve($abstract, ...)
{
if ($this->asyncMode && $this->isScoped($abstract)) {
$ctx = current_context();
if ($instance = $ctx->find($abstract)) {
return $instance;
}
$instance = $this->buildFresh($abstract);
$ctx->set($abstract, $instance);
return $instance;
}
return parent::resolve($abstract, ...);
}
Kontextové klíče přes enum a řešení pro Facades
Pro vyhnutí se kolizím a zajištění bezpečného přístupu se používají enum klíče:
enum ScopedService: string
{
case REQUEST = 'request';
case SESSION = 'session';
case AUTH = 'auth';
case AUTH_DRIVER = 'auth.driver';
case COOKIE = 'cookie';
}
To poskytuje:
- Izolaci přístupu (pouze vlastník enum může číst/psát data)
- Záruku absence kolizí (i při stejných řetězcových hodnotách)
- Podporu statické analýzy (PHPStan/IDE sledují použití)
Facades vyžadovaly samostatné řešení kvůli cachování resolvedInstance ve statickém poli. Implementován ScopedServiceProxy:
class ScopedServiceProxy
{
public function __call($method, $args)
{
return ($this->resolver)()->$method(...$args);
}
}
Proxy přesměrovává volání do kontextu aktuální korutiny a udržuje cache na úrovni proxy.
Kritické adaptace a PDO Pool
Po základní izolaci se projevily služby ukládající stav na požadavek uvnitř sebe. Byly potřeba specializované async verze:
- AsyncRouter (izolace aktuální trasy)
- AsyncDispatcher (odložené události na korutinu)
- AsyncTranslator (lokalizace překladů)
- AsyncViewFactory (View::share())
- AsyncConfig (změny konfigurace za běhu)
- AsyncDatabaseSessionHandler (atomární zápis session)
- Async\*Connection (počítadlo transakcí)
Osobitá pozornost věnována práci s DB. Bez poolu spojení souběžné dotazy z korutin porušují protokol PostgreSQL. TrueAsync to řeší vestavěným PDO Pooolem:
$pdo = new PDO($dsn, $user, $password, [
PDO::ATTR_POOL_ENABLED => true,
PDO::ATTR_POOL_MIN => 0,
PDO::ATTR_POOL_MAX => 10,
PDO::ATTR_POOL_HEALTHCHECK_INTERVAL => 30,
]);
Pool dynamicky rozděluje spojení: po obdržení výsledku SELECT se spojení vrátí do poolu a obslouží více korutin, než je maximální velikost poolu. Pro transakce se spojení fixuje do commit/rollback.
Co je důležité
- TrueAsync eliminuje problém barevných funkcí modifikací jádra PHP
- Stateful služby Laravel vyžadují kontextovou izolaci přes current_context()
- PDO Pool je klíčový pro správnou práci s DB v konkurenčním prostředí
- Enum klíče zajišťují bezpečnost a sledovatelnost kontextových dat
- Řešení nenahrazuje vícevláknovost pro úlohy vázané na CPU
— Editorial Team
Zatím žádné komentáře.