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

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

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

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