Async PHP (Sunshine)

Async PHP (Sunshine)

PHP has emerged from it’s dark past; just in time to learn from the advances in event-based programming languages/platforms. As a result; there is vast, untapped potential in developing event-based, real-time applications. Utilising emerging open-source projects, PHP developers can join the party.

061e3bae4ce4234a2194d20a382e5d19?s=128

Christopher Pitt

February 06, 2016
Tweet

Transcript

  1. async php

  2. thanks sunshine

  3. thanks silverstripe

  4. story 'me

  5. you can write async code

  6. spreading work to other threads

  7. forking

  8. $pid = pcntl_fork(); if ($pid) { // you're in the

    parent process pcntl_waitpid($pid, $status, WUNTRACED); if ($status > 0) { // handle the error } } else { // do something in the child process if ($failed) { exit(1); } exit(0); }
  9. php.net/manual/en/book.pcntl.php

  10. leanpub.com/signalingphp

  11. threading

  12. class MyThread extends Thread { public $hasLicense = null; private

    $repository; public function __construct($repository) { $this->repository = escapeshellarg($repository); } public function run() { $folder = hash("sha256", $this->repository); exec("git clone " . $this->repository . " " . $folder); chdir(__DIR__ . "/" . $folder); $this->hasLicense = preg_grep("/^LICENSE/i", glob("*")); } }
  13. $thread = new MyThread("git@github.com:php/php-src.git"); if ($thread->start()) { $thread->join(); // do

    something with $thread->hasLicense }
  14. php.net/manual/en/book.pthreads.php

  15. pthreads.org

  16. spreading the work to other machines

  17. message queues

  18. $pheanstalk = new Pheanstalk\Pheanstalk("127.0.0.1"); $pheanstalk->useTube("sunshine")->put("a message"); // some time later...

    $message = $pheanstalk->watch("sunshine")->reserve(); $pheanstalk->delete($message);
  19. $context = new ZMQContext(); $socket = new ZMQSocket($context, ZMQ::SOCKET_PUSH); $socket->connect("tcp://127.0.0.1:5555");

    $socket->send("a message"); // some time later $socket = new ZMQSocket($context, ZMQ::SOCKET_PULL); $socket->bind("tcp://127.0.0.1:5555"); $message = $socket->recv();
  20. you can also use rabbit mq, amazon sqs, and iron

    mq
  21. gearman

  22. $client = new GearmanClient(); $client->addServer("127.0.0.1", 4730); $client->setCompleteCallback(function(GearmanTask $task) { //

    so domething when the task is complete }); $task = $client->addTask("inspect", "some data"); $client->runTasks();
  23. $worker = new GearmanWorker(); $worker->addServer("127.0.0.1", 4730); $worker->addFunction("inspect", function(GearmanJob $job) {

    // do the job, with $job->workload() }); while ($worker->work()) { if ($worker->returnCode() !== GEARMAN_SUCCESS) { // something went wrong } }
  24. php.net/manual/en/book.gearman.php

  25. async standard library

  26. amphp, icicle, react...

  27. explicit event loops

  28. use Icicle\Http\Message\BasicResponse; use Icicle\Http\Message\Request; use Icicle\Http\Server\RequestHandler; use Icicle\Socket\Socket; use Icicle\Stream\MemorySink;

    class MyRequestHandler implements RequestHandler { public function onRequest(Request $request, Socket $socket): Generator { $stream = new MemorySink(); yield from $stream->end("hello world"); yield new BasicResponse(200, [ "Content-Type" => "text/plain", "Content-Length" => $stream->getLength(), ], $stream); } public function onError(int $code, Socket $socket): Generator { yield new BasicResponse($code); } }
  29. use Icicle\Http\Server\Server; use Icicle\Loop; $server = new Server(new MyRequestHandler()); $server->listen(81,

    "127.0.0.1"); $server->listen(82, "127.0.0.1"); Loop\run();
  30. server { listen 80; server_name acme.com; location / { proxy_set_header

    X-Real-IP $remote_addr; proxy_set_header Host $http_host; proxy_pass http://127.0.0.1:81; } }
  31. use Icicle\Http\Message\Request; use Icicle\Http\Message\Response; use Icicle\Socket\Socket; use Icicle\WebSocket\Application; use Icicle\WebSocket\Connection;

    use Icicle\WebSocket\Message; class MyApplication implements Application { public function onHandshake(Response $response, Request $request, Socket $socket): Generator { yield $response; } public function onConnection(Connection $connection): Generator { $iterator = $connection->read()->getIterator(); while (yield $iterator->isValid()) { // $iterator->getCurrent() + $connection->send(new Message()) } $connection->close(); } }
  32. use Icicle\Http\Message\BasicResponse; use Icicle\Http\Message\Request; use Icicle\Http\Server\RequestHandler; use Icicle\Socket\Socket; use Icicle\WebSocket\Application;

    use Icicle\WebSocket\Server\Server; class MyRequestHandler implements RequestHandler { private $application; public function __construct(Application $application) { $this->application = $application; } public function onRequest(Request $request, Socket $socket): Generator { yield $this->application; } public function onError($code, Socket $socket): Generator { yield new BasicResponse($code); } } $server = new Server(new MyRequestHandler(new MyApplication()));
  33. 1. corou'nes 2. promises + observables 3. streams 4. filesystem

    5. dns 6. threading + forking
  34. icicle.io/docs

  35. examples

  36. github.com/asyncphp

  37. why [i think] you should try async

  38. value for you

  39. value for the community

  40. I don't get why people can't deal with async environments.

    Cause, for me, it's like the dream. — @dead_lugosi
  41. want to know more about this stuff?

  42. assertchris.io/asyncphp

  43. If I said to you in 2000 that one day

    PHP would have any kind of strict mode, you would have laughed in my face.
  44. It isn't the year 2000 any more ... it's nature

    is, to a large degree, dictated by RFCs that pass the vote ...
  45. And while you will hear people use it's nature to

    argue against certain features, those voices aren't enough to stand in the way of progress. — @krakjoe
  46. joind.in/talk/84ad6

  47. thanks! twi$er.com/assertchris