brebvix/workerman
Composer 安装命令:
composer require brebvix/workerman
包简介
An asynchronous event driven PHP framework for easily building fast, scalable network applications.
关键字:
README 文档
README
What is it
Workerman is an asynchronous event driven PHP framework with high performance for easily building fast, scalable network applications. Supports HTTP, Websocket, SSL and other custom protocols. Supports libevent, HHVM , ReactPHP.
Requires
PHP 5.3 or Higher
A POSIX compatible operating system (Linux, OSX, BSD)
POSIX and PCNTL extensions for PHP
Yii2
Installation
composer require brebvix/workerman
Basic Usage
A websocket server
<?php use brebvix\Worker; // Create a Websocket server $ws_worker = new Worker("websocket://0.0.0.0:2346"); // 4 processes $ws_worker->count = 4; // Emitted when new connection come $ws_worker->onConnect = function($connection) { echo "New connection\n"; }; // Emitted when data received $ws_worker->onMessage = function($connection, $data) { // Send hello $data $connection->send('hello ' . $data); }; // Emitted when connection closed $ws_worker->onClose = function($connection) { echo "Connection closed\n"; }; // Run worker Worker::runAll();
An http server
require_once __DIR__ . '/vendor/autoload.php'; use brebvix\Worker; // #### http worker #### $http_worker = new Worker("http://0.0.0.0:2345"); // 4 processes $http_worker->count = 4; // Emitted when data received $http_worker->onMessage = function($connection, $data) { // $_GET, $_POST, $_COOKIE, $_SESSION, $_SERVER, $_FILES are available var_dump($_GET, $_POST, $_COOKIE, $_SESSION, $_SERVER, $_FILES); // send data to client $connection->send("hello world \n"); }; // run all workers Worker::runAll();
A WebServer
require_once __DIR__ . '/vendor/autoload.php'; use brebvix\WebServer; use brebvix\Worker; // WebServer $web = new WebServer("http://0.0.0.0:80"); // 4 processes $web->count = 4; // Set the root of domains $web->addRoot('www.your_domain.com', '/your/path/Web'); $web->addRoot('www.another_domain.com', '/another/path/Web'); // run all workers Worker::runAll();
A tcp server
require_once __DIR__ . '/vendor/autoload.php'; use brebvix\Worker; // #### create socket and listen 1234 port #### $tcp_worker = new Worker("tcp://0.0.0.0:1234"); // 4 processes $tcp_worker->count = 4; // Emitted when new connection come $tcp_worker->onConnect = function($connection) { echo "New Connection\n"; }; // Emitted when data received $tcp_worker->onMessage = function($connection, $data) { // send data to client $connection->send("hello $data \n"); }; // Emitted when new connection come $tcp_worker->onClose = function($connection) { echo "Connection closed\n"; }; Worker::runAll();
Enable SSL
<?php require_once __DIR__ . '/vendor/autoload.php'; use brebvix\Worker; // SSL context. $context = array( 'ssl' => array( 'local_cert' => '/your/path/of/server.pem', 'local_pk' => '/your/path/of/server.key', 'verify_peer' => false, ) ); // Create a Websocket server with ssl context. $ws_worker = new Worker("websocket://0.0.0.0:2346", $context); // Enable SSL. WebSocket+SSL means that Secure WebSocket (wss://). // The similar approaches for Https etc. $ws_worker->transport = 'ssl'; $ws_worker->onMessage = function($connection, $data) { // Send hello $data $connection->send('hello ' . $data); }; Worker::runAll();
Custom protocol
Protocols/MyTextProtocol.php
namespace Protocols; /** * User defined protocol * Format Text+"\n" */ class MyTextProtocol { public static function input($recv_buffer) { // Find the position of the first occurrence of "\n" $pos = strpos($recv_buffer, "\n"); // Not a complete package. Return 0 because the length of package can not be calculated if($pos === false) { return 0; } // Return length of the package return $pos+1; } public static function decode($recv_buffer) { return trim($recv_buffer); } public static function encode($data) { return $data."\n"; } }
require_once __DIR__ . '/vendor/autoload.php'; use brebvix\Worker; // #### MyTextProtocol worker #### $text_worker = new Worker("MyTextProtocol://0.0.0.0:5678"); $text_worker->onConnect = function($connection) { echo "New connection\n"; }; $text_worker->onMessage = function($connection, $data) { // send data to client $connection->send("hello world \n"); }; $text_worker->onClose = function($connection) { echo "Connection closed\n"; }; // run all workers Worker::runAll();
Timer
require_once __DIR__ . '/vendor/autoload.php'; use brebvix\Worker; use brebvix\Lib\Timer; $task = new Worker(); $task->onWorkerStart = function($task) { // 2.5 seconds $time_interval = 2.5; $timer_id = Timer::add($time_interval, function() { echo "Timer run\n"; } ); }; // run all workers Worker::runAll();
AsyncTcpConnection (tcp/ws/text/frame etc...)
require_once __DIR__ . '/vendor/autoload.php'; use brebvix\Worker; use brebvix\Connection\AsyncTcpConnection; $worker = new Worker(); $worker->onWorkerStart = function() { // Websocket protocol for client. $ws_connection = new AsyncTcpConnection("ws://echo.websocket.org:80"); $ws_connection->onConnect = function($connection){ $connection->send('hello'); }; $ws_connection->onMessage = function($connection, $data){ echo "recv: $data\n"; }; $ws_connection->onError = function($connection, $code, $msg){ echo "error: $msg\n"; }; $ws_connection->onClose = function($connection){ echo "connection closed\n"; }; $ws_connection->connect(); }; Worker::runAll();
Async Mysql of ReactPHP
composer require react/mysql
<?php require_once __DIR__ . '/vendor/autoload.php'; use brebvix\Worker; $worker = new Worker('tcp://0.0.0.0:6161'); $worker->onWorkerStart = function() { global $mysql; $loop = Worker::getEventLoop(); $mysql = new React\MySQL\Connection($loop, array( 'host' => '127.0.0.1', 'dbname' => 'dbname', 'user' => 'user', 'passwd' => 'passwd', )); $mysql->on('error', function($e){ echo $e; }); $mysql->connect(function ($e) { if($e) { echo $e; } else { echo "connect success\n"; } }); }; $worker->onMessage = function($connection, $data) { global $mysql; $mysql->query('show databases' /*trim($data)*/, function ($command, $mysql) use ($connection) { if ($command->hasError()) { $error = $command->getError(); } else { $results = $command->resultRows; $fields = $command->resultFields; $connection->send(json_encode($results)); } }); }; Worker::runAll();
Async Redis of ReactPHP
composer require clue/redis-react
<?php require_once __DIR__ . '/vendor/autoload.php'; use Clue\React\Redis\Factory; use Clue\React\Redis\Client; use brebvix\Worker; $worker = new Worker('tcp://0.0.0.0:6161'); $worker->onWorkerStart = function() { global $factory; $loop = Worker::getEventLoop(); $factory = new Factory($loop); }; $worker->onMessage = function($connection, $data) { global $factory; $factory->createClient('localhost:6379')->then(function (Client $client) use ($connection) { $client->set('greeting', 'Hello world'); $client->append('greeting', '!'); $client->get('greeting')->then(function ($greeting) use ($connection){ // Hello world! echo $greeting . PHP_EOL; $connection->send($greeting); }); $client->incr('invocation')->then(function ($n) use ($connection){ echo 'This is invocation #' . $n . PHP_EOL; $connection->send($n); }); }); }; Worker::runAll();
Aysnc dns of ReactPHP
composer require react/dns
require_once __DIR__ . '/vendor/autoload.php'; use brebvix\Worker; $worker = new Worker('tcp://0.0.0.0:6161'); $worker->onWorkerStart = function() { global $dns; // Get event-loop. $loop = Worker::getEventLoop(); $factory = new React\Dns\Resolver\Factory(); $dns = $factory->create('8.8.8.8', $loop); }; $worker->onMessage = function($connection, $host) { global $dns; $host = trim($host); $dns->resolve($host)->then(function($ip) use($host, $connection) { $connection->send("$host: $ip"); },function($e) use($host, $connection){ $connection->send("$host: {$e->getMessage()}"); }); }; Worker::runAll();
Http client of ReactPHP
composer require react/http-client
<?php require_once __DIR__ . '/vendor/autoload.php'; use brebvix\Worker; $worker = new Worker('tcp://0.0.0.0:6161'); $worker->onMessage = function($connection, $host) { $loop = Worker::getEventLoop(); $client = new \React\HttpClient\Client($loop); $request = $client->request('GET', trim($host)); $request->on('error', function(Exception $e) use ($connection) { $connection->send($e); }); $request->on('response', function ($response) use ($connection) { $response->on('data', function ($data) use ($connection) { $connection->send($data); }); }); $request->end(); }; Worker::runAll();
ZMQ of ReactPHP
composer require react/zmq
<?php require_once __DIR__ . '/vendor/autoload.php'; use brebvix\Worker; $worker = new Worker('text://0.0.0.0:6161'); $worker->onWorkerStart = function() { global $pull; $loop = Worker::getEventLoop(); $context = new React\ZMQ\Context($loop); $pull = $context->getSocket(ZMQ::SOCKET_PULL); $pull->bind('tcp://127.0.0.1:5555'); $pull->on('error', function ($e) { var_dump($e->getMessage()); }); $pull->on('message', function ($msg) { echo "Received: $msg\n"; }); }; Worker::runAll();
STOMP of ReactPHP
composer require react/stomp
<?php require_once __DIR__ . '/vendor/autoload.php'; use brebvix\Worker; $worker = new Worker('text://0.0.0.0:6161'); $worker->onWorkerStart = function() { global $client; $loop = Worker::getEventLoop(); $factory = new React\Stomp\Factory($loop); $client = $factory->createClient(array('vhost' => '/', 'login' => 'guest', 'passcode' => 'guest')); $client ->connect() ->then(function ($client) use ($loop) { $client->subscribe('/topic/foo', function ($frame) { echo "Message received: {$frame->body}\n"; }); }); }; Worker::runAll();
Available commands
php start.php start
php start.php start -d
php start.php status
php start.php connections
php start.php stop
php start.php restart
php start.php reload
Documentation
中文文档: http://doc.workerman.net
Documentation:https://github.com/walkor/workerman-manual
Benchmarks
CPU: Intel(R) Core(TM) i3-3220 CPU @ 3.30GHz and 4 processors totally
Memory: 8G
OS: Ubuntu 14.04 LTS
Software: ab
PHP: 5.5.9
Codes
<?php use brebvix\Worker; $worker = new Worker('tcp://0.0.0.0:1234'); $worker->count=3; $worker->onMessage = function($connection, $data) { $connection->send("HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nServer: brebvix\r\nContent-Length: 5\r\n\r\nhello"); }; Worker::runAll();
Result
ab -n1000000 -c100 -k http://127.0.0.1:1234/ This is ApacheBench, Version 2.3 <$Revision: 1528965 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 127.0.0.1 (be patient) Completed 100000 requests Completed 200000 requests Completed 300000 requests Completed 400000 requests Completed 500000 requests Completed 600000 requests Completed 700000 requests Completed 800000 requests Completed 900000 requests Completed 1000000 requests Finished 1000000 requests Server Software: workerman/3.1.4 Server Hostname: 127.0.0.1 Server Port: 1234 Document Path: / Document Length: 5 bytes Concurrency Level: 100 Time taken for tests: 7.240 seconds Complete requests: 1000000 Failed requests: 0 Keep-Alive requests: 1000000 Total transferred: 73000000 bytes HTML transferred: 5000000 bytes Requests per second: 138124.14 [#/sec] (mean) Time per request: 0.724 [ms] (mean) Time per request: 0.007 [ms] (mean, across all concurrent requests) Transfer rate: 9846.74 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.0 0 5 Processing: 0 1 0.2 1 9 Waiting: 0 1 0.2 1 9 Total: 0 1 0.2 1 9 Percentage of the requests served within a certain time (ms) 50% 1 66% 1 75% 1 80% 1 90% 1 95% 1 98% 1 99% 1 100% 9 (longest request)
Other links with workerman
PHPSocket.IO
php-socks5
php-http-proxy
Donate
LICENSE
Workerman is released under the MIT license.
brebvix/workerman 适用场景与选型建议
brebvix/workerman 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 2.25k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2018 年 10 月 26 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「event-loop」 「asynchronous」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 brebvix/workerman 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 brebvix/workerman 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 brebvix/workerman 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Asynchronous coroutines for PHP 7.
Wrapper around proc_open to ease communication via streams between processes
An asynchronous event driven PHP framework for easily building fast, scalable network applications.
Symfony ResqueBundle
Generic PHP Threads library using only pure PHP
Development and debugging tools for Recoil applications.
统计信息
- 总下载量: 2.25k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 9
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2018-10-26