Giter Club home page Giter Club logo

reactphp's Introduction

ReactPHP Logo

Event-driven, non-blocking I/O with PHP.

Build Status

ReactPHP is a low-level library for event-driven programming in PHP. At its core is an event loop, on top of which it provides low-level utilities, such as: Streams abstraction, async DNS resolver, network client/server, HTTP client/server and interaction with processes. Third-party libraries can use these components to create async network clients/servers and more.

<?php

// $ composer require react/http react/socket # install example using Composer
// $ php example.php # run example on command line, requires no additional web server

require __DIR__ . '/vendor/autoload.php';

$server = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
    return React\Http\Message\Response::plaintext(
        "Hello World!\n"
    );
});

$socket = new React\Socket\SocketServer('127.0.0.1:8080');
$server->listen($socket);

echo "Server running at http://127.0.0.1:8080" . PHP_EOL;

This simple web server written in ReactPHP responds with "Hello World!" for every request.

ReactPHP is production ready and battle-tested with millions of installations from all kinds of projects around the world. Its event-driven architecture makes it a perfect fit for efficient network servers and clients handling hundreds or thousands of concurrent connections, long-running applications and many other forms of cooperative multitasking with non-blocking I/O operations. What makes ReactPHP special is its vivid ecosystem with hundreds of third-party libraries allowing you to integrate with many existing systems, such as common network services, database systems and other third-party APIs.

  • Production ready and battle-tested.
  • Rock-solid with stable long-term support (LTS) releases.
  • Requires no extensions and runs on any platform - no excuses!
  • Takes advantage of optional extensions to get better performance when available.
  • Highly recommends latest version of PHP 7+ for best performance and support.
  • Supports legacy PHP 5.3+ and HHVM for maximum compatibility.
  • Well designed and reusable components.
  • Decoupled parts so they can be replaced by alternate implementations.
  • Carefully tested (unit & functional).
  • Promotes standard PSRs where possible for maximum interoperability.
  • Aims to be technology neutral, so you can use your preferred application stack.
  • Small core team of professionals supported by large network of outside contributors.

ReactPHP is non-blocking by default. Use workers for blocking I/O. The event loop is based on the reactor pattern (hence the name) and strongly inspired by libraries such as EventMachine (Ruby), Twisted (Python) and Node.js (V8).

This repository you're currently looking at is mostly used as a meta repository to discuss and plan all things @ReactPHP. See the individual components linked below for more details about each component, its documentation and source code.

Core Components

Network Components

Utility Components

Built with ReactPHP

  • Thruway PHP Client and Router Library for Autobahn and WAMP (Web Application Messaging Protocol) for Real-Time Application Messaging voryx/Thruway

  • PPM - PHP Process Manager PPM is a process manager, supercharger and load balancer for modern PHP applications. php-pm/php-pm

  • php-ar-drone 🚁 Port of node-ar-drone which allows user to control a Parrot AR Drone over PHP jolicode/php-ar-drone

  • Ratchet Asynchronous WebSocket server ratchetphp/Ratchet

  • Predis\Async Asynchronous PHP client library for Redis built on top of ReactPHP nrk/predis-async

  • clue/redis-server A Redis server implementation in pure PHP clue/redis-server

And many more on our wiki page »

Articles

  • Sergey Zhuk A series of articles covering ReactPHP: from the basics to the real application examples. sergeyzhuk.me

  • Cees-Jan Kiewiet Blog series about several ReactPHP components and how they work. blog.wyrihaximus.net

  • Loïc Faugeron Super Speed Symfony - ReactPHP. gnugat.github.io

  • Marc J. Schmidt Bring High Performance Into Your PHP App (with ReactPHP). marcjschmidt.de

  • Marc Morera When ReactPHP meet Symfony medium.com/@apisearch

Talks

Getting started

ReactPHP consists of a set of individual components. This means that instead of installing something like a "ReactPHP framework", you actually pick only the components that you need.

This project follows SemVer for all its stable components. The recommended way to install these components is through Composer. New to Composer?

For example, this may look something like this:

# recommended install: pick required components
composer require react/event-loop react/http

As an alternative, we also provide a meta package that will install all stable components at once. Installing this is only recommended for quick prototyping, as the list of stable components may change over time. This meta package can be installed like this:

# quick protoyping only: install all stable components
composer require react/react:^1.4

For more details, check out ReactPHP's homepage for quickstart examples and usage details.

See also the combined changelog for all ReactPHP components for details about version upgrades.

Support

Do you have a question and need help with ReactPHP? Don't worry, we're here to help!

As a first step, check the elaborate documentation that comes with each component (see links to individual documentation for each component above). If you find your question is not answered within the documentation, there's a fair chance that it may be relevant to more people. Please do not hesitate to file your question as an issue in the relevant component so others can also participate.

You can also check out our official Gitter chat room. Most of the people involved in this project are available in this chat room, so many questions get answered in a few minutes to some hours. We also use this chat room to announce all new releases and ongoing development efforts, so consider staying in this chat room for a little longer.

Also follow @reactphp on Twitter for updates. We use this mostly for noteworthy, bigger updates and to keep the community updated about ongoing development efforts. You can always use the #reactphp hashtag if you have anything to share!

We're a very open project and we prefer public communication whenever possible, so that more people can participate and help getting the best solutions available. At the same time, we realize that some things are better addressed in private. Whether you just want to say thank you, want to report a security issue or want to help sponsor a certain feature development, you can reach out to the core team in private by sending an email to [email protected]. Please keep in mind that we're a small team of volunteers and do our best to support anybody reaching out.

Do you want to support ReactPHP? Awesome! Let's start with letting the the world know why you think ReactPHP is awesome and try to help others getting on board! Send a tweet, write a blog post, give a talk at your local user group or conference or even write a book. There are many ways you can help. You can always reach out to us in private and help others in our support channels. Thank you!

Tests

To run the test suite, you first need to clone this repo and then install all dependencies through Composer:

composer install

To run the test suite, go to the project root and run:

vendor/bin/phpunit

The test suite also contains a number of functional integration tests that rely on a stable internet connection. Due to the vast number of integration tests, these are skipped by default during CI runs. If you also do not want to run these, they can simply be skipped like this:

vendor/bin/phpunit --exclude-group internet

License

MIT, see LICENSE.

reactphp's People

Contributors

arghav avatar arnaud-lb avatar cameronjacobson avatar cboden avatar clue avatar cystbear avatar e3betht avatar elliot avatar h4cc avatar hannesvdvreken avatar igorw avatar irvyne avatar jmalloc avatar jmikola avatar jsor avatar lt avatar mmoreram avatar mykiwi avatar nhedger avatar nielsvanpach avatar nrk avatar pborreli avatar reedy avatar robinvdvleuten avatar romainneutron avatar sgoettschkes avatar simonfrings avatar whatthejeff avatar wyrihaximus avatar yuya-takeyama avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

reactphp's Issues

[Http] Implement full HTTP/1.1 spec

Some todos:

  • delimit requests by empty body, content-length or chunked encoding (as defined by the RFC)
  • keepalive
  • 100-continue handling (could be improved by adding a separate event for that header)
  • pipelining
  • multipart parsing (inspiration)

We also need to decide how to handle encoding of outgoing data. There are different use cases for modifying the response, some of which may require buffering: websockets, gzip compression, chunked encoding.

[EventLoop] libevent timersgc broken in some cases

If you remove the testAddPeriodicTimerCancelsItself method from React\Tests\EventLoop\Timer\LibEventTimerTest you will notice the following error:

PHP Fatal error: Cannot destroy active lambda function in /Users/igor/code/react/src/React/EventLoop/LibEventLoop.php on line 179

Ping @cameronjacobson.

Drop espresso from core

Espresso in its current form is only a proof of concept. As such, I think we should drop it from the core project and move it to a third party dependency.

This will allow similar third party frameworks to arise without putting too much weight on the unstable espresso component itself.

Poke @cboden.

popen() streams sometimes block the event loop

I'm writing a small application using React and Ratchet that opens up a few long-running external processes, and redirects some of their output (via stdout) through a websocket connection.

Using popen and React's stream class to talk to the external process usually works just fine, and the process's output gets sent to the websocket as it executes -- as one would expect. Some processes, however, block the event loop until they've completed running.

Inside my Ratchet application, I can run

$ping = new Stream(popen("ping -t 127.0.0.1",'r'),$server->loop);
$ping->on('data',function($data) use ($from){
    $from->send($data);
});

and ping will continuously direct its output through my websocket connection, $from.

However, if I use a different executable (in this case, the Adobe F4V Post-Processor), I get no output from f4vpp, or anything else in my event loop (say, the ping command above) until f4vpp exits.

$f4vpp = new Stream(popen("f4vpp -v -i in.f4v -o out.mp4",'r'),$server->loop);
$f4vpp->on('data',function($data) use ($from){
    $from->send($data);
});

What's going on here? Is this user error, or a legitimate shortcoming in React or PHP on win32?

Simple Method to GZIP Response

Right now there doesn't seem to be a simple way to automatically gzip responses and attach the appropriate content-encoding header. Right now you have to do something like this:

$app->get('/', function(React\Http\Request $request, React\Http\Response $response) use (&$i) {

    $text = gzencode("A generic response with gzip.\n");

    $headers = array('Content-Encoding' => 'gzip',
                     'Content-Type' => 'text/plain', 
                     'Content-Length' => strlen($text));

    $response->writeHead(200, $headers);
    $response->end($text);
});

Which works but this gets tedious and I believe its a common enough (and expected) feature that even forcing people to implement an abstraction themselves isn't the best path.

Challenges

I'd like to put up some challenges on the website. This should give people some idea what to work on. Please suggest more here as well.

  • DNS Client: #19
  • Http Client (curl_multi with Loop::addPeriodicTimer)
  • Libev EventLoop: #32

fully-asynchronous http requests

There is an issue with doing non-blocking HTTP requests with stream functions: fopen actually returns only after the server has sent the response headers, which can cause the script to block for some times.

It would be awesome if react-php allowed to do fully-asynchronous HTTP requests.

Libevent does not like file streams on linux

You cannot poll file streams with epoll. Libevent does not handle this gracefully and throws awful errors in your face.

We should detect the epoll backend in the libevent event loop and instead of adding file streams to the event loop, add them to a separate array and consider it always ready.

We might be able to find out if a stream is a file stream by using stream_get_meta_data. I really hope a PHP stream cannot change from memory to file dynamically. If that is the case, we're kind of screwed with libevent.

Interface or component for workers

Sometimes apps will need synchronous I/O. This should not take place in the event loop, as it would block everything. Instead, it should be distributed to workers.

React should provide some way to interface with these workers (workers should use pre-forking). This could be a simple message queue abstraction interface or possibly a full-blown component that provides integration with redis, zeromq, maybe even rabbitmq (if somebody makes a non-blocking client lib).

Installation problem

Problem when using composer to install react on ubuntu 12.04.

My composer.json file is:
{
"require": {
"react/react": "dev-master"
}
}

Terminal output:

$ composer install
Installing dependencies
Your requirements could not be solved to an installable set of packages.

Problems:
    - Problem caused by:
        - Package "react/react-9999999-dev" contains the rule react/react requires evenement/evenement (== 9999999-dev). Any of these packages satisfy the dependency: evenement/evenement-9999999-dev.
        - Installation request for react/react == 9999999-dev: Satisfiable by [react/react-dev-master].
        - Package "guzzle/guzzle-2.5.0.0" contains the rule guzzle/guzzle requires ext-curl ([]). No package satisfies this dependency.

[EventLoop] libevent can't close connection

Here is the code I was using against the master branch: https://gist.github.com/2653190

If I call $conn->end() the client receives the write buffer (HTTP Response) but the connection does not close. If I call $conn->close() the server does close the connection, but does not receive the write buffer.

  • Mac OS 10.7.3
  • libevent 2.0.17-stable
  • php libevent bindings v0.0.5

[Socket] Semantics

Thinking at a high level here, I'd like to propose ConnectionInterface methods be renamed to from write to send or deliver and end to disconnect.

write means write some data to a stream. Now that we have buffering and async I/O send makes more sense. We're not writing bytes to a buffer, we've abstracted that, the user is sending a message. It makes more sense the higher up we go in the chain. Request::send, from the users perspective, is sending a whole message where the abstraction is writing bytes when the buffer is available.

I find end unclear. A Connection is a proxy representation of a connected client/user. Would documentation read "Call end() to end the connection to the user"? I find disconnect to be much more succinct.

Require PHP 5.4

PHP 5.4.0 was released on 01-Mar-2012. The end of life for PHP 5.3.x is in March 2013.

The major decision factor is a) ease of getting started; b) ease of deployment.

Getting started

In case users do not have PHP 5.4.x on their local machines, we must provide install instructions. For example, OSX ships with 5.3, so we should point users to either php-osx or homebrew-php.

This seems like an acceptable requirement to me.

Deployment

It is critical that major distros ship with PHP 5.4 before we bump the requirement.

  • Ubuntu and Fedora are already doing so.
  • Debian will ship with it in the next release. Which will be around Feb/Mar 2013.
  • I wasn't able to find any info on Centos and RedHat.

Proposal

IMO we should wait at least until debian wheezy is out. Which would mean bumping whenever that happens, hopefully within the next 2-3 months.

Feedback please.

LibEventLoop timers leaking memory

Reproduce script:

<?php

// script to test for mem leaks
// You can test it using:
// siege localhost:8080

require __DIR__.'/../vendor/autoload.php';

$loop = new React\EventLoop\LibEventLoop();
$socket = new React\Socket\Server($loop);
$http = new React\Http\Server($socket, $loop);

$i = 0;

$http->on('request', function ($request, $response) use ($loop, &$i) {
    $i++;
    $response->writeHead();
    $response->end("Hello World!\n");

    $loop->addTimer(1, function () {
        // noop
    });
});

$loop->addPeriodicTimer(2, function () use (&$i) {
    $kmem = memory_get_usage(true) / 1024;
    echo "Request: $i\n";
    echo "Memory: $kmem KiB\n";
});

$socket->listen(8080);
$loop->run();
$ siege -c 50 localhost:8080

Memory keeps increasing, something is not being cleaned up properly.

Vagrant

A very nice to have would be a Vagrant setup for React. Someone looking to poke around with React but not ready to install libs on their system. Recipes would include:

  • composer
  • PHP 5.4 with extensions:
  • libevent + PHP libevent extension (0.0.5+)
  • libev + PHP libev extension (travis example)
  • ZeroMQ + PHP ZeroMQ bindings (travis example)

Not sure if this would be in /vagrant of React repo or a separate sandbox repo - open to suggestions.

Edit: Links fixed
Edit2: Removed dual PHP installation

[EventLoop] Timed events

According to the comments on the libevent PHP manual page, libevent supports timed events through the undocumented event_timer_new function.

For StreamSelectLoop we could re-implement it by checking the time within tick.

@nrk is working on this.

Memory leak in HttpClient

Considering this script :

<?php

include 'vendor/autoload.php';

use React\Dns\Resolver\Factory as DnsResolverFactory;
use React\HttpClient\ConnectionManager;
use React\HttpClient\SecureConnectionManager;
use React\HttpClient\Client;
use React\EventLoop\Factory as LoopFactory;
use React\HttpClient\Response;

$loop = LoopFactory::create();

$dnsResolverFactory = new DnsResolverFactory();
$dnsResolver = $dnsResolverFactory->createCached('8.8.8.8', $loop);

$connectionManager = new ConnectionManager($loop, $dnsResolver);
$secureConnectionManager = new SecureConnectionManager($loop, $dnsResolver);
$client = new Client($loop, $connectionManager, $secureConnectionManager);

$reference = memory_get_usage();

$loop->addPeriodicTimer(1, function () use ($client, &$reference) {
    $request = $client->request('GET', 'http://127.0.0.1:80/');
    $request->writeHead();

    $memory = memory_get_usage();
    echo sprintf("memory usage : %d, delta : %d\n", $memory, $memory - $reference);
    $reference = $memory;
});

$loop->run();

and the output :

memory usage : 1625544, delta : 906936
memory usage : 1834208, delta : 208664
memory usage : 1852904, delta : 18696
memory usage : 1871600, delta : 18696
memory usage : 1890296, delta : 18696
memory usage : 1908992, delta : 18696
memory usage : 1927688, delta : 18696
memory usage : 1946384, delta : 18696
memory usage : 1965080, delta : 18696
memory usage : 1983776, delta : 18696
memory usage : 2002472, delta : 18696
memory usage : 2021168, delta : 18696
memory usage : 2039864, delta : 18696
memory usage : 2058560, delta : 18696
memory usage : 2077256, delta : 18696

It seems a leak happens.

This happens with both StreamSelectLop and LibEventLoop. The leak stops if $request->writeHead(); is commented

Unsupressed warning in React\Socket\Server.php

Line 20 of the file React\Socket\Server.php raises a PHP warning if the PHP function stream_socket_server() is unable to connect to the specified host and port, e.g.

stream_socket_server(): unable to connect to tcp://0.0.0.0:80

The warning should be supressed via @, so the fixed section would look like as follows:

<?php
///...
$this->master = @stream_socket_server("tcp://$host:$port", $errno, $errstr);
// if (false ...

memory leak socket-based middleware (with solution)

I encountered symptoms of a memory leak while writing some simple middleware for a 3rd party socket-based application. The solution can be found in the following gist.

Note the calls to gc_enable() and gc_collect_cycles().

EDIT: technically not a memory leak, but named as such to hopefully get the attention of folks thinking this is what they're experiencing.

https://gist.github.com/4060804

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.