Výběr technologií je významnou fází vývoje jakéhokoliv software. Tato fáze se nedá přeskočit a silně bych nedoporučoval ji jakkoliv podcenit. V našem případě do hry vstupovalo několik proměnných. Sestupně podle důležitosti:

  1. Na prvním místě zkušenosti. Tím ovšem nemám na mysli použití osvědčených technologií. Mám na mysli poučení se z předchozích chyb.
  2. Nejnovější technologie
  3. Znalosti

Tyto řádky bych rád věnoval druhému bodu, protože je pro nás nejen klíčovým, ale také nás zcela vystihuje.

  • PHP7 je dělo se striktním typováním
  • PHP-PM, které využíváme, je postaveno na ReactPHP. Jsou to technologie zcela nové. Čas od času sami najdeme chybu a přispějeme Pull Requestem, který chybu odstraňuje. Kolem PHP-PM vzniká poměrně hezká komunita. Když jsme se k němu dostali, bylo to o několika málo lidech.
  • Angular2 je takovou celosvětovou tikající bombou. K dnešnímu dni používáme verzi RC1. Musíme uznat, že vyvíjet v tom aplikaci stojí dost nervů. Vývojáři vám to doslova mění pod rukama. Ve čtvrtky bývá téměř vždy venku release, který často přináší spousty změn a vylepšení. Angular2 je postaven na straně klienta, kde ve své podstatě běží. Se serverem komunikuje skrz WebScoket pomocí BrowserSync. BrowserSync je, mimochodem, moc zajímavý projekt. Primárně určený k debugování aplikace. Dokáže synchronizovat prohlížeče mezi sebou a simulovat tak práci na několika zařízeních (když například napíšu nějaký text na mobilu do inputu, na desktopu se mi před očima v reálném čase objevují písmenka). Tím bych se odkázal na svou diplomovou práci z roku 2014, kde tuto problematiku rozebírám podrobně.
  • a další.

Tedy k PHP-PM. ProcessManager je, již z názvu, procesem, který řídí další procesy. V průběhu několika let se přístup k PHP aplikacím „změnil“. V uvozovkách proto, protože stále existuje mnoho IT firem a jednotlivců, kteří si toho nevšimli. Existuje stále spousta programátorů, kteří nevyužívají žádný framework. Je opravdu buřt jaký, ale alespoň nějaký. Na frameworku pracují samotní vývojáři, dále komunita nadšenců a uživatelů. Není vůbec důvod polemizovat o tom, jestli je váš kód čistší, než ve frameworku. Nikdy není! (Jako Zenďák si to myslím.)

ProcessManager běží a neumírá. Již v PHP nepracujeme jako

Start -> Handle Request -> Response -> Die

nové schéma může vypadat takto

Bootstrap -> Start -> [ Handle Request -> Response ]*

toto má neskutečnou výhodu v tom, že věci zůstávají v paměti. PHP je stále jazyk, který je převáděn do strojového kódu (opcode) při každém spuštění aplikace. Myšlenka still-alive aplikace tedy tví v tom, že aplikace se přeloží jen jednou a poté stále běží. Zní to složitě, pokud jste se nesetkali s Request/Response frameworkem (ZF2, Symfony, Nette, Laravel, …). Složité to ale není. Frameworky mají bootstrap. V Zendu je to Application::init. Init vrací instanci aplikace a ta zatím nic neprovedla. Čeká na zavolání run a na nastavení Requestu. Po skočení je navrácen Response. V něm je cokoliv, co aplikace generuje (html, json, nebo jiná čertovina).

Na PHP-PM se udává, že tento způsob pojetí aplikací, zvyšuje rychlost aplikace až na 15 násobek. My můžeme potvrdit:

  • asi 15 násobek oproti Apache + PHP
  • asi 12 násobek oproti Apache + PHP-FPM
  • asi 6 násobek oproti Nginx + PHP-FPM

PHP-PM tím, že běží jako proces, startuje jako server přímo přes konzoli.

# !/bin/s
./bin/ppm start

k tomu také náleží soubor pm.json, ve kterém je konfigurace PM.

{
  "bridge": "MyPHPPM\\Admin\\Bridges\\Admin",
  "host": "127.0.0.1",
  "port": 8080,
  "workers": 8,
  "app-env": "dev",
  "debug": 1,
  "logging": 1,
  "bootstrap": "MyPHPPM\\Admin\\Bootstraps\\Admin",
  "max-requests": 1000,
  "concurrent-requests": 0,
  "cgi-path": "/usr/bin/php-cgi",
  "static": 1
}

Tím server startne na portu 8080 a v nginx nastavíte ProxyPass na 127.0.0.1:8080. Spustí 8 workerů, kteří obsluhují requesty. Workeři jsou zcela individuální nastavení. Doporučujeme reflektovat počet jader procesoru ;)

Pro ZendFramework existuje PHP-PM adapter, který nastiňuje, jak by to asi mohlo fungovovat: ZDE. Podle našich zkušeností a několika dní ladění to považujeme pouze za inspirační, protože vypluje na povrch mnoho problémů a nestandardního chování. Například je nutné si uvědomit, že při používání ServiceManager se objevuje nutnost služby flushnout. Když proces neumírá, ale jen čeká na další request, tak se nezničí ani objekty, které jsou v procesu vytvořeny. Musíte s tím počítat. V krajním případě je flushnout

<?php
$_sm = $app->getServiceManager();
$_sm->configure(['services' => ['ServiceNameToFlush' => null]]);

Dalším problémem může být cirkulární reference. V PHP je garbage collector, který funguje automaticky, pokud je zapnut. Vám vyvstává povinnost se o aplikaci starat trochu více, než jen zprasit kód a nasrat, však to stejně chcípne. Doporučujeme nastudovat, jak funguje gc a jak používat gc_collect_cycles. unset často stačí k úspěšnému destructu. Problém je s referencemi uvnitř objektu. Kdy to nestačí:

<?php
declare(strict_types = 1);

class A {
    protected $b;
    
    publc function __construct(B $b){
        $this->b = $b
    }
}

class B {
    protected $a;
    
    public funciton setA(A $a){
        $this->a = $a;
    }
}

$b = new B;
$a = new A($b);
$b->setA($a);

unset($b);
unset($a);

To je ale na úplně jiný článek. Více i v článku na alexnet.com

Pozor na php_session. Stává se zde dost nebezpečnou, proto doporučuji pídit se po alternativách. V implementaci je vidět, že se uchovává session_id

Suma sumárum je pár komplikací, které nejsou neřešitelné. To je absolutně směšná daň za takovýto výkon. Pokud toužíte po tom, aby vaši uživatelé, nebo zákazníci pocítili opravdu znatelné zrychlení, ReactPHP je jasná volba.

Kromě PHP-PM existuje více projektů postavených na Reactu. Může to být třeba BunnyPHP, na kterém sviští třeba skrz.cz