Čo presne Octane mení
Pri klasickom PHP-FPM requeste sa pri každom volaní vykoná: autoload tried, registrácia a boot všetkých service providerov, zostavenie service container, spustenie middleware pipeline. Pri jednoduchom JSON endpointe je táto bootstrap fáza často drahšia než samotná business logika.
Laravel Octane appku naštartuje jeden raz a uloží ju do pamäte dlhotrvajúceho procesu (Swoole, RoadRunner alebo FrankenPHP). Každý ďalší request len prejde cez už zostavený container — bootstrap sa neopakuje. Cenou je, že sa musíte sami postarať o vyčistenie stavu medzi requestmi, ktoré by inak PHP-FPM zahodil automaticky ukončením procesu.
Swoole vs. RoadRunner vs. FrankenPHP
| Runtime | Jazyk jadra | Inštalácia | Odporúčanie |
|---|---|---|---|
| Swoole | C (PHP extension) | pecl install swoole | Najrýchlejší, vyžaduje kompiláciu rozšírenia |
| RoadRunner | Go (samostatný binárny proces) | Stiahnutie binárky, žiadna kompilácia PHP | Najjednoduchšia inštalácia na zdieľanom VPS |
| FrankenPHP | Go + PHP (jeden binárny server) | Jeden statický binár, nahradí aj Nginx | Najnovšia voľba, výborná pre Docker |
Pre väčšinu projektov na VPS odporúčam RoadRunner — nevyžaduje kompiláciu PHP rozšírenia a má jednoduchší deployment. Swoole má o niečo vyšší strop výkonu a podporuje coroutines pre konkurentné úlohy.
Inštalácia
composer require laravel/octane
# Interaktívne vyberie server (Swoole / RoadRunner / FrankenPHP)
php artisan octane:install
Pre RoadRunner príkaz stiahne binárku rr do koreňa projektu. Server zvoľte aj explicitne v .env:
OCTANE_SERVER=roadrunner
Spustenie a konfigurácia workerov
# Vývoj
php artisan octane:start
# Produkcia — počet worker procesov podľa CPU jadier
php artisan octane:start --workers=4 --task-workers=2 --port=8000
--workers určuje počet procesov, ktoré spracúvajú HTTP requesty paralelne. --task-workers je oddelený pool pre asynchrónne úlohy spustené cez Octane::concurrently() — vhodné napríklad na paralelné API volania bez blokovania hlavného workera.
Najväčšie úskalie: zdieľaný stav medzi requestmi
V klasickom PHP-FPM modeli sa po každom requeste celá pamäť procesu zahodí. V Octane appka žije ďalej — a s ňou aj všetko, čo ste si nechtiac uložili do statickej premennej alebo singletonu.
// NEBEZPEČNÉ v Octane — pole rastie pri každom requeste a nikdy sa nevyprázdni
class RequestLogger
{
public static array $log = [];
public function record(string $message): void
{
self::$log[] = $message; // Po tisíckach requestov zožerie všetku RAM
}
}
// NEBEZPEČNÉ — singleton si „zapamätá" prvého užívateľa pre všetky ďalšie requesty
$this->app->singleton(CurrentTenant::class, function () {
return new CurrentTenant(auth()->user()?->tenant_id); // Vyhodnotené len raz!
});
// app/Providers/AppServiceProvider.php
public function boot(): void
{
// Vyčistenie vlastného stavu medzi requestmi
if (class_exists(\Laravel\Octane\Facades\Octane::class)) {
\Laravel\Octane\Facades\Octane::tick('clear-static-log', function () {
RequestLogger::$log = [];
})->seconds(60);
}
}
Čo Octane resetuje automaticky, a čo nie
- Resetuje automaticky: väzby v service containeri vytvorené cez
bind(), request-scoped dáta (request(), session, autentifikovaný užívateľ pri novom requeste) - Neresetuje: statické vlastnosti tried, singletony s dátami vypočítanými pri boote, globálne premenné, otvorené file handles alebo DB spojenia podržané mimo Eloquentu
- Konfiguráciu a routy Octane cachuje pri starte — zmena
.envalebo route definícií vyžadujephp artisan octane:reload
Nasadenie na produkciu: Nginx + systemd
Octane proces musí bežať ako démon. Nginx pred ním slúži ako reverse proxy a zabezpečuje SSL terminovanie — rovnaký princíp ako pri nasadení Laravel Reverb.
# /etc/systemd/system/laravel-octane.service
[Unit]
Description=Laravel Octane Application Server
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/php artisan octane:start --server=roadrunner --host=127.0.0.1 --port=8000 --workers=4
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
# /etc/nginx/sites-available/myapp
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
systemctl restart laravel-octane) — appka bežiaca v pamäti inak ďalej obsluhuje starý kód. Zaraďte tento krok do CI/CD pipeline, ktorú rozoberám v článku o automatickom nasadení cez GitHub Actions.
Kedy Octane nie je vhodný
- Zdieľaný hosting bez root prístupu — Octane potrebuje vlastný dlhotrvajúci proces, nie len PHP-FPM pool
- Staršie balíky so globálnym stavom — knižnice, ktoré spoliehajú na to, že proces žije len jeden request, môžu v Octane spôsobiť úniky alebo nesprávne dáta
- Veľmi nízka návštevnosť — pri desiatkach requestov denne sa zložitosť navyše (monitoring memory leakov, reštarty po deployi) nevyplatí oproti jednoduchému PHP-FPM
Záver: checklist pred nasadením
- Žiadna statická premenná ani singleton neuchováva dáta špecifické pre jedného užívateľa
- Octane proces beží ako systemd service s
Restart=always - Deploy skript obsahuje
octane:reloadalebo reštart služby po každej zmene kódu - Počet workerov je naladený podľa reálneho počtu CPU jadier na serveri
- Monitoring sleduje rast spotreby RAM v čase — postupný nárast signalizuje memory leak