Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Асинхронный PHP

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

Асинхронный PHP

Avatar for Roman Pronskiy

Roman Pronskiy

November 23, 2017
Tweet

Other Decks in Programming

Transcript

  1. О СЕБЕ • Chief Software Engineer @ EPAM Systems •

    PHP, JavaScript, Python • Автор PHP Дайджестов на Хабрахабре • Twitter: @pronskiy • GitHub: @pronskiy
  2. КОНКУРЕНТНОСТЬ В PHP • pthreads • popen() • proc_open() •

    pcntl_fork() • socket_select() • stream_select() • stream_set_blocking() • curl_multi_select()
  3. EVENT LOOP // select(2) • stream_select // poll, epoll, /dev/poll/,

    kqueue • libev • libevent • event • libuv
  4. Набор компонентов 5 лет, production ready Хороший API Активная разработка

    Хорошее сообщество Много документации и примеров, есть книга Версия 1.0.0 в конце 2017 PHP 5.4+ Не поддерживается HTTP keep-alive Нет HTTP 2.0 ReactPHP
  5. ReactPHP 1 const http = require('http'); 2 3 const server

    = http.createServer((req, res) => { 4 res.statusCode = 200; 5 res.setHeader('Content-Type', 'text/plain'); 6 res.end('Hello World\n'); 7 }); 8 9 server.listen('8081', '127.0.0.1'); NodeJS 1 use React\Http\Server; 2 use React\Http\Response; 3 4 $server = new Server(function ($req) { 5 return new Response( 6 200, 7 ['Content-Type' => 'text/plain'], 8 "Hello World!\n" 9 ); 10 }); 11 12 $loop = React\EventLoop\Factory::create(); 13 $socket = new React\Socket\Server(8081, $loop); 14 $server->listen($socket); 15 16 $loop->run(); ReactPHP
  6. Amp Набор компонентов На основе генераторов (корутин) Совместим с библиотеками

    для ReactPHP HTTP-компонент поддерживает HTTP/2.0 Активно развивается PHP 7.0+ Плохая документация Не очень красивый API
  7. Amp 1 const express = require('express'); 2 const app =

    express(); 3 4 app.get('/', (req, res) => { 5 res.send('Hello World') 6 }); 7 8 app.listen(8081, '127.0.0.1'); NodeJS / express Amp / aerys 1 use Aerys\Host; 2 use function Aerys\router; 3 4 $host = new Host(); 5 $host->expose('127.0.0.1', 8081); 6 $host->use(router()); 7 8 $router->get('/', function($req, $res) { 9 $res->end('Hello World'); 10 });
  8. Workerman 1 const http = require('http'); 2 3 const server

    = http.createServer((req, res) => { 4 res.statusCode = 200; 5 res.setHeader('Content-Type', 'text/plain'); 6 res.end('Hello World\n'); 7 }); 8 9 server.listen('8081', '127.0.0.1'); NodeJS 1 use Workerman\Worker; 2 3 $worker = new Worker("http://0.0.0.0:8081"); 4 5 $worker->onMessage = function($connection, $data) { 6 // $_GET, $_POST, $_COOKIE, 7 // $_SESSION, $_SERVER, $_FILES are available 8 $connection->send("Hello World\n"); 9 }; 10 11 Worker::runAll(); Workerman
  9. Swoole Написана на С Использует epoll/kqueue Очень высокая производительность Много

    собственных компонентов из коробки Своя реализация многопоточности Корутины и каналы а-ля Go Активно развивается PHP 5.5+ Made in China Поставляется в виде расширения Местами уродливый API
  10. Swoole 1 const http = require('http'); 2 3 const server

    = http.createServer((req, res) => { 4 res.statusCode = 200; 5 res.setHeader('Content-Type', 'text/plain'); 6 res.end('Hello World\n'); 7 }); 8 9 server.listen('8081', '127.0.0.1'); NodeJS 1 $server = new swoole_http_server("127.0.0.1", 8081); 2 3 $server->on("request", function ($req, $res) { 4 $res->status(200); 5 $res->header("Content-Type", "text/plain"); 6 $res->end("Hello World\n"); 7 }); 8 9 $server->start(); Swoole
  11. php-pm • Менеджер процессов и балансировщик нагрузки • Производительность до

    15x (по сравнению с PHP-FPM на Symfony) • Hot-Code reload • Поддержка HttpKernel (Symfony/Laravel), Drupal (experimental), Zend (experimental) • Можно использовать как замену nginx+php-fpm в микросервисе
  12. stream_select Лимит дескрипторов = 1024 • Перекомпилировать php с увеличением

    FD_SETSIZE • Использовать другой Event Loop: • libev (pecl-ev PHP 7) • event • libuv (PHP 7.0+) • swoole • Балансировать нагрузку
  13. ИЗБЕГАЙТЕ БЛОКИРОВАНИЯ • Запросы к БД • Файловые операции •

    file_get_contents • file_exists • get_mime_type • Сетевые операции • Запросы к сторонним API • Зависимости • Каждая из библиотек может делать что-то из этого
  14. ТЯЖЕЛЫЕ CPU ОПЕРАЦИИ • Сложные алгоритмы • Обработка больших кусков

    данных • Разбивать на куски • $loop->nextTick(callable)
  15. АНОНИМНЫЕ ФУНКЦИИ • Нет короткого синтаксиса (есть RFC) • Только

    явное объявление переменных из внешнего скоупа • Не забывать делать это по ссылке • Код становится шумный 1 return function (ConnectionInterface $connection) use ($index, &$clientReceivedFIN, &$clientSentFIN) { 2 $client = $connection; 3 $client->resume(); 4 $client->on('end', function () use ($index, $client, &$clientSentFIN) { 5 $this->loop->addTimer(0.05, function () use ($index, $client, &$clientSentFIN) { 6 $writeResult = $client->write($index); 7 $client->end(); 8 $clientSentFIN++; 9 }); 10 }); 11 $client->on('close', function () use ($index, &$clientReceivedFIN) { 12 $clientReceivedFIN++; 13 }); 14 };
  16. ПЕРСПЕКТИВЫ Fiber • RFC • Stackful корутины • По сути

    замыкания, которые можно ставить на паузу и возобновлять • Планирование (scheduling) выполняется в юзерлэнд, а не в VM • github.com/fiberphp
  17. ВЫВОДЫ В нашем мире не все, всегда и везде, a

    кое-что, иногда и местами. PHP Async Async PHP