Event-driven PHP engines
Bài đăng này đã không được cập nhật trong 7 năm
Traditional PHP serving style assumes it to always run behind web-server, which uses default PHP interpreter or FPM pool to handle requests. This brings limitations, which are the main arguments in criticizing PHP:
- Every request is being handled separately and memory is freed after request. All the code needs to be recompiled and re-executed.
- Most asynchronous features like tasks or realtime interactions require using third-party languages like nodejs.
How it works?
On the opposite to FPM, event-driven PHP works more like most concurrent engines (Node.js for example) and serves from PHP itself.
There are 2 most popular alternatives: Workerman, which is written with PHP and Swoole, available as PECL component and written in C.
Why Swoole?
Swoole includes components for different purposes: Server, Task Worker, Timer, Event and Async IO. With these components, Swoole allows you to build many features.
The following code will launch a basic echo server.
// create a server instance
$serv = new swoole_server("127.0.0.1", 9501);
// attach handler for connect event, once client connected to server the registered handler will be executed
$serv->on('connect', function ($serv, $fd){
echo "Client:Connect.\n";
});
// attach handler for receive event, every piece of data received by server, the registered handler will be
// executed. And all custom protocol implementation should be located there.
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
$serv->send($fd, $data);
});
$serv->on('close', function ($serv, $fd) {
echo "Client: Close.\n";
});
// start our server, listen on port and ready to accept connections
$serv->start();
Looks a lot like Express.js code, right?
HTTP connections
For HTTP the special swoole_http_server
should be created. It allows to listen to HTTP requests and handle them with a Closure
having two arguments: function (swoole_http_request $request, swoole_http_response $response) { … }
$http = new swoole_http_server("0.0.0.0", 9501);
$http->on('request', function ($request, $response) {
$response->header("Content-Type", "text/html; charset=utf-8");
$response->end("<h1>Hello Swoole. #".rand(1000, 9999)."</h1>");
});
$http->start();
The swoole_http_request
object contains all expected data from request: $get
, $post
, $header
, $server
, $cookie
, $files
, $fd
as key-value arrays.
This allows to simply map the request object to PSR-7 or Symfony HTTP Request or any other framework.
The swoole_http_response
object allows to pass the result to server response.
The class provides following methods:
end()
— End Http response, send HTML contentwrite()
— Send Http chunk of data to the browserheader()
— Add a header to responsecookie()
— Set a cookiestatus()
— Set Http Status Code, such as 404, 501, 200gzip()
— Set http compression format
Websockets
Websockets can also be easily implemented and run with PHP-only environment.
$ws = new swoole_websocket_server("0.0.0.0", 9502);
$ws->on('open', function ($ws, $request) {
var_dump($request->fd, $request->get, $request->server);
$ws->push($request->fd, "hello, welcome\n");
});
$ws->on('message', function ($ws, $frame) {
echo "Message: {$frame->data}\n";
$ws->push($frame->fd, "server: {$frame->data}");
});
$ws->on('close', function ($ws, $fd) {
echo "client-{$fd} is closed\n";
});
$ws->start();
Integrations
Both Workerman and Swoole can be easily integrated with Laravel, Symphony and Yii2 by using third-party packages.
For Laravel garveen/laravoole
is available and supports Laravel versions up to 5.3.
Performance
Developers of the engines promise up to 10x performance increase comparing to default PHP-FPM configuration.
This makes sense as PHP code is not being unloaded from memory anymore and doesn’t require continuous compilation on every request.
In comparison of Swoole and Workerman, the first gives slightly higher performance on the same configuration:
swoole\http\server
Requests per second: 67213.61 [#/sec] (mean)
walkor/Workerman
Requests per second: 41669.86 [#/sec] (mean)
Links
- GitHub - swoole/swoole-src: Event-driven asynchronous & concurrent & coroutine networking engine with high performance for PHP.
- GitHub - walkor/Workerman: An asynchronous event driven PHP framework for easily building fast, scalable network applications. Supports HTTP, Websocket and other custom protocols. Supports libevent, HHVM, ReactPHP.
- GitHub - garveen/laravoole: Laravel && ( Swoole || Workerman ) to get 10x faster than php-fpm
All rights reserved