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

React (phpbnl13)

React (phpbnl13)

A4b95be2145cc46f891707b6db9dd82d?s=128

Igor Wiedler

January 26, 2013
Tweet

Transcript

  1. None
  2. Y U NO PHP?

  3. @igorwesome

  4. None
  5. None
  6. None
  7. var http = require('http'); var server = new http.Server(); server.on('request',

    function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }); server.listen(1337, '127.0.0.1');
  8. None
  9. $server = stream_socket_server('tcp://127.0.0.1:1337'); while ($conn = stream_socket_accept($server, -1)) { fwrite($conn,

    "HTTP/1.1 200 OK\r\n"); fwrite($conn, "Content-Length: 3\r\n\r\n"); fwrite($conn, "Hi\n"); fclose($conn); }
  10. $s=stream_socket_server('tcp://[::1]:81'); while($c=stream_socket_accept($s,-1)) fwrite($c,"HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nHi");

  11. Non-blocking I/O

  12. C10K

  13. Calculations are fast, I/O is slow.

  14. Latency Comparison Numbers -------------------------- L1 cache reference 0.5 ns Branch

    mispredict 5 ns L2 cache reference 7 ns Mutex lock/unlock 25 ns Main memory reference 100 ns Compress 1K bytes with Zippy 3,000 ns Send 1K bytes over 1 Gbps network 10,000 ns 0.01 ms Read 4K randomly from SSD* 150,000 ns 0.15 ms Read 1 MB sequentially from memory 250,000 ns 0.25 ms Round trip within same datacenter 500,000 ns 0.5 ms Read 1 MB sequentially from SSD* 1,000,000 ns 1 ms Disk seek 10,000,000 ns 10 ms Read 1 MB sequentially from disk 20,000,000 ns 20 ms Send packet CA->Netherlands->CA 150,000,000 ns 150 ms
  15. Latency Comparison Numbers -------------------------- L1 cache reference 0.5 ns Branch

    mispredict 5 ns L2 cache reference 7 ns Mutex lock/unlock 25 ns Main memory reference 100 ns Compress 1K bytes with Zippy 3,000 ns Send 1K bytes over 1 Gbps network 10,000 ns 0.01 ms Read 4K randomly from SSD* 150,000 ns 0.15 ms Read 1 MB sequentially from memory 250,000 ns 0.25 ms Round trip within same datacenter 500,000 ns 0.5 ms Read 1 MB sequentially from SSD* 1,000,000 ns 1 ms Disk seek 10,000,000 ns 10 ms Read 1 MB sequentially from disk 20,000,000 ns 20 ms Send packet CA->Netherlands->CA 150,000,000 ns 150 ms
  16. None
  17. stream_select

  18. $readable = $read ?: null; $writable = $write ?: null;

    $except = null; if (stream_select($readable, $writable, $except, 1)) { if ($readable) { foreach ($readable as $stream) { ... } } if ($writable) { foreach ($writable as $stream) { ... } } }
  19. $readable = $read ?: null; $writable = $write ?: null;

    $except = null; if (stream_select($readable, $writable, $except, 1)) { if ($readable) { foreach ($readable as $stream) { ... } } if ($writable) { foreach ($writable as $stream) { ... } } } Event Loop
  20. None
  21. None
  22. Event-driven, non-blocking I/O with PHP.

  23. Demo

  24. $loop = React\EventLoop\Factory::create(); $socket = new React\Socket\Server($loop); $http = new

    React\Http\Server($socket, $loop); $http->on('request', function ($req, $rep) { $rep->writeHead(); $rep->end("Hello World!\n"); }); $socket->listen(8080); $loop->run();
  25. $loop = React\EventLoop\Factory::create(); $socket = new React\Socket\Server($loop); $socket->on('connection', function ($conn)

    { $conn->pipe($conn); }); $socket->listen(4000); $loop->run();
  26. None
  27. # composer.json { "require": { "react/http": "0.2.*" } }

  28. $ composer install

  29. Philosophy

  30. Architecture

  31. Événement EventEmitter for PHP

  32. $emitter = new Evenement\EventEmitter(); $emitter->on('data', function ($data) { echo $data;

    }); $emitter->emit('data', [$data]);
  33. EventLoop Stream Socket Http

  34. EventLoop $loop = React\EventLoop\Factory::create(); $server = stream_socket_server('tcp://127.0.0.1:8080'); stream_set_blocking($server, 0); $loop->addReadStream($server,

    function ($server) use ($loop) { $conn = stream_socket_accept($server); ... });
  35. EventLoop $loop->addPeriodicTimer(5, function () { $memory = memory_get_usage() / 1024;

    $formatted = number_format($memory, 3).'K'; echo "Current memory usage: {$formatted}\n"; });
  36. EventLoop $loop->run();

  37. EventLoop backends stream_select libevent libev upcoming libuv

  38. ReadableStream isReadable() pause() resume() close() Events data, end, error, close

    Stream
  39. ReadableStream isReadable() pause() resume() close() Events data, end, error, close

    Stream
  40. WritableStream isWritable() write($data) end($data) close() Events drain, error, close, pipe

    Stream
  41. WritableStream isWritable() write($data) end($data) close() Events drain, error, close, pipe

    Stream
  42. Stream $source = new React\Stream\Stream(fopen('omg.txt', 'r'), $loop); $dest = new

    React\Stream\Stream(fopen('wtf.txt', 'w'), $loop); $source->pipe($dest);
  43. Stream $a->pipe($b)->pipe($c); a | b | c

  44. Socket $socket = new React\Socket\Server($loop); $socket->on('connection', function ($conn) { $conn->write("Hello

    there!\n"); $conn->write("Welcome to this amazing server!\n"); $conn->write("Here's a tip: don't say anything.\n"); $conn->on('data', function ($data) use ($conn) { $conn->close(); }); }); $socket->listen(1337);
  45. Http $socket = new React\Socket\Server($loop); $http = new React\Http\Server($socket); $http->on('request',

    function ($request, $response) { $response->writeHead(200, ['Content-Type' => 'text/plain']); $response->end("Hello World!\n"); }); $socket->listen(1337);
  46. EventLoop Stream Socket Http

  47. Http HttpClient DNS

  48. HttpClient Http DNS Stomp Whois

  49. HttpClient Http DNS Stomp Whois WebSocket DNode SOCKS IRC

  50. None
  51. $foo->get(function ($bar) { $bar->get(function ($baz) { $baz->get(function ($bazinga) { $bazinga->get(function

    () { throw new FuckItException(); }); }); }); });
  52. async API (escaping callback hell)

  53. React/Async

  54. use React\Async\Util as Async; Async::waterfall([ function ($callback) use ($foo) {

    $foo->get($callback); }, function ($bar, $callback) { $bar->get($callback); }, function ($baz, $callback) { $baz->get($callback); }, function ($bazinga, $callback) { $bazinga->get($callback); }, function ($callback) { throw new FuckItException(); } ]);
  55. React/Promise

  56. $dns ->resolve('igor.io') ->then(function ($ip) { echo "Host: $ip\n"; });

  57. $promise ->then('doStuff') ->then('doMoreStuff') ->then('explosion') ->then(null, function ($e) { echo "[Error]

    {$e->getMessage()}\n"; });
  58. Deferred Promise Resolver Consumer Producer then() resolve() reject()

  59. Streams

  60. Readable Writable

  61. Readable Writable Through

  62. Readable Writable Through Composite

  63. Buffered Sink

  64. Bi-directional

  65. conn logger parser $conn->pipe($inputLogger)->pipe($parser);

  66. parser client $parser->on('message', function ($message) use ($client) { $client->say('pong'); });

  67. client conn logger $client->pipe($outputLogger)->pipe($conn);

  68. conn parser client conn

  69. Houston we have a blocking call

  70. Inter-process communication

  71. React/ZMQ

  72. $context = new React\ZMQ\Context($loop); $push = $context->getSocket(ZMQ::SOCKET_PUSH); $push->connect('tcp://127.0.0.1:5555'); $push->send('hello');

  73. React/Stomp Predis/Async DNode-PHP

  74. RealtimeWeb™

  75. Ratchet

  76. gifsockets!!!11

  77. None
  78. None
  79. None
  80. Questions? • joind.in/7805 • reactphp.org • @reactphp • @igorwesome

  81. Questions? • joind.in/7805 • reactphp.org • @reactphp • @igorwesome

  82. Http Server Worker Client Worker Worker Client Client HTTP