Skrz.cz hlídá každé uživatelovo prohlédnutí nabídky. Jsou to miliony pidirequestů denně. Použít PHP-FPM by znamenalo zbytečně další server(y). ReactPHP díky asynchronnímu IO dovoluje s minimálními nároky zpracovávat tisíce req/s. Nechtěli jsme se vzdát Symfony, a tak vznikl bridge mezi Symfony a asynchronním světem ReactPHP.
1 of 15
Download to read offline
More Related Content
ReactPHP + Symfony = profit aneb 1000req/s přes Symfony s minimálními nároky na server (1. sraz přátel Symfony v Praze, 29.10.2015)
1. ReactPHP + Symfony = PROFIT
aneb 1000req/s s minimálními nároky na server
1. sraz přátel Symfony v Praze (29.10.2015)
Skrz.cz hlídá každé uživatelovo prohlédnutí nabídky. Jsou to miliony
pidirequestů denně. Použít PHP-FPM by znamenalo zbytečně další
server(y). ReactPHP díky asynchronnímu IO dovoluje s minimálními
nároky zpracovávat tisíce req/s. Nechtěli jsme se vzdát Symfony, a
tak vznikl bridge mezi Symfony a asynchronním světem ReactPHP.
2. Slovníček
• klik = najedu myší na nabídku a zmáčknu tlačítko
• imprese = podíval jsem se na nabídku
(alespoň polovina nabídky byla ve viewportu
alespoň jednu sekundu)
• CTR (click-through rate) = kliky / imprese
Průměrné CTR display reklamy v ČR je 0.08%
(viz http://www.richmediagallery.com/tools/
benchmarks). Když máte 1 klik za sekundu,
každou sekundu k němu přijde ještě přes 1000
impresí.
3. Takovýhle banner můžete vidět třeba na
Novinky.cz. Jedná se právě o tu
“display reklamu”. Tady Skrz měří tisíce
impresí za sekundu.
4. Uvnitř Skrzu se opět měří každé zobrazení. Tam je
analytika o to složitější, že se zobrazení musí správně
napárovat na plochu, kde k němu došlo (boxík “Moje
navštívené”, boxík “Nejprodávanější”, ostatní výpisy, s
každou novou feature plochy vznikají a zanikají).
Impresí už není tolik, zato obsahují více dat. Taky má
Skrz řádově lepší CTR, a tudíž více prokliků.
5. ReactPHP
(neplést s ReactJS!)
http://reactphp.org/
(https://github.com/jakubkulhan/hit-server-bench)
Impresí je tedy hodně. Ale i ty “velké” na Skrzu jsou pořád malinkaté requesty. Největší
zátěz je na IO (čtení/zápis do databáze, resp. čtení/zápis do RabbitMQ).
Řešil jsem, co použít pro takového jednoduché “hitování” serveru. Performance výsledky
k porovnání jsou v odkazovaném repozitáři “hit-server-bench”.
Jelikož PHP a ReactPHP zvládaly dostatečný počet req/s a datový model byl již udělán v
PHP, vyplatilo se zainvestovat do ReactPHP - mohou se používat stejné objekty jako ve
zbytku aplikace. Nechtělo se mi vzdát Symfony dependency injection containeru a
routingu, a tak vznikl bridge mezi ReactPHP a Symfony.
6. ReactPHP: req, res → λ → void
Symfony: req → λ → res
❓
Problém se vyskytl hned na začátku. Zatímco
ReactPHP předá fci pro zpracování requestu 2
objekty - request a response a nic neočekává na
výstupu; Symfony proteče request a na výstupu
je očekávána response.
7. req → λ → promise[res]
❗
Řešení se ukázalo jednoduché. Symfony
na výstupu vydá “promise” - objekt, který
zastupuje výsledek výpočtu, který třeba
ještě ani nemusel proběhnout. V ReactPHP
se počká na výsledek promisu a ten se
poté zapíše do response objektu.
13. Controller
/**
* @Controller
*/
class IndexController
{
/**
* @var LoopInterface
*
* @Autowired
*/
public $loop;
public function indexAction(Request $request)
{
return Response::create("Hello, world!n");
}
public function promiseAction(Request $request)
{
$secs = intval($request->attributes->get("secs"));
$deferred = new Deferred();
$this->loop->addTimer($secs, function () use ($secs, $deferred) {
$deferred->resolve(Response::create("{$secs} seconds later...n"));
});
return $deferred->promise();
}
}
14. Knihovny
• ReactPHP (např. HTTP klient, ZeroMQ)
https://github.com/reactphp
• MySQL
https://github.com/kaja47/async-mysql
https://github.com/KhristenkoYura/react-mysql
https://github.com/bixuehujin/reactphp-mysql
• Redis
https://github.com/nrk/predis-async
• RabbitMQ
https://github.com/jakubkulhan/bunny
V ReactPHP je potřeba používat speciální
knihovny, které využijí asynchronicity
(použitím synchronní knihovny byste úplně
znegovaly výhody, které ReactPHP má.)
Tučně jsou zvýrazněny ty, co má Skrz
nasazeny v produkci.
15. Díky!
Otázky?
Dobrá otázka byla: “Použil bys ReactPHP a
Symfony znovu, kdybys stejnou aplikaci stavěl
teď?”
Je důležité uvědomit si, že v době psaní aplikace
(říjen/listopad 2014), byl stack ve Skrzu PHP-only.
Jelikož ReactPHP splňoval výkonové požadavky,
dávalo smysl neuhýbat od PHP. V situaci, co jsme
byli, bych se opět rozhodl stejně.
Od té doby však ve Skrzu přibyl do stack ještě
Golang. Dnes bych již tuhle aplikaci pro sledování
impresí napsal v Golangu.