Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/walkor/workerman
An asynchronous event driven PHP socket framework. Supports HTTP, Websocket, SSL and other custom protocols.
https://github.com/walkor/workerman
asynchronous event-driven high-performance php socket socket-server tcp timer websocket ws wss
Last synced: 3 days ago
JSON representation
An asynchronous event driven PHP socket framework. Supports HTTP, Websocket, SSL and other custom protocols.
- Host: GitHub
- URL: https://github.com/walkor/workerman
- Owner: walkor
- License: mit
- Created: 2013-12-08T07:49:28.000Z (about 11 years ago)
- Default Branch: master
- Last Pushed: 2024-10-29T09:18:13.000Z (4 months ago)
- Last Synced: 2024-10-29T09:58:43.569Z (4 months ago)
- Topics: asynchronous, event-driven, high-performance, php, socket, socket-server, tcp, timer, websocket, ws, wss
- Language: PHP
- Homepage: http://www.workerman.net
- Size: 3.63 MB
- Stars: 11,154
- Watchers: 465
- Forks: 2,260
- Open Issues: 86
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: MIT-LICENSE.txt
- Security: SECURITY.md
Awesome Lists containing this project
- php-awesome - **Workerman** - PHP Socket服务器框架 (基础框架 / 构建/部署)
- StarryDivineSky - walkor/workerman
README
# Workerman
[](https://gitter.im/walkor/Workerman?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge)
[](https://packagist.org/packages/workerman/workerman)
[](https://packagist.org/packages/workerman/workerman)
[](https://packagist.org/packages/workerman/workerman)
[](https://packagist.org/packages/workerman/workerman)
[](https://packagist.org/packages/workerman/workerman)## What is it
Workerman is an asynchronous event-driven PHP framework with high performance to build fast and scalable network applications. It supports HTTP, WebSocket, custom protocols, coroutines, and connection pools, making it ideal for handling high-concurrency scenarios efficiently.## Requires
A POSIX compatible operating system (Linux, OSX, BSD)
POSIX and PCNTL extensions required
Event/Swoole/Swow extension recommended for better performance## Installation
```
composer require workerman/workerman
```## Documentation
[https://manual.workerman.net](https://manual.workerman.net)
## Basic Usage
### A websocket server
```php
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
```php
use Workerman\Worker;require_once __DIR__ . '/vendor/autoload.php';
// #### 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, $request) {
//$request->get();
//$request->post();
//$request->header();
//$request->cookie();
//$request->session();
//$request->uri();
//$request->path();
//$request->method();// Send data to client
$connection->send("Hello World");
};// Run all workers
Worker::runAll();
```### A tcp server
```php
use Workerman\Worker;require_once __DIR__ . '/vendor/autoload.php';
// #### 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 connection is closed
$tcp_worker->onClose = function ($connection) {
echo "Connection closed\n";
};Worker::runAll();
```### Enable SSL
```php
[
'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();
```### AsyncTcpConnection (tcp/ws/text/frame etc...)
```phpuse Workerman\Worker;
use Workerman\Connection\AsyncTcpConnection;require_once __DIR__ . '/vendor/autoload.php';
$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();
```### Coroutine
Coroutine is used to create coroutines, enabling the execution of asynchronous tasks to improve concurrency performance.
```php
eventLoop = Swoole::class; // Or Swow::class or Fiber::class$worker->onMessage = function (TcpConnection $connection, Request $request) {
Coroutine::create(function () {
echo file_get_contents("http://www.example.com/event/notify");
});
$connection->send('ok');
};Worker::runAll();
```> Note: Coroutine require Swoole extension or Swow extension or [Fiber revolt/event-loop](https://github.com/revoltphp/event-loop), and the same applies below
### Barrier
Barrier is used to manage concurrency and synchronization in coroutines. It allows tasks to run concurrently and waits until all tasks are completed, ensuring process synchronization.```php
eventLoop = Swoole::class; // Or Swow::class or Fiber::class
$worker->onMessage = function (TcpConnection $connection, Request $request) {
$barrier = Barrier::create();
for ($i=1; $i<5; $i++) {
Coroutine::create(function () use ($barrier, $i) {
file_get_contents("http://127.0.0.1:8002?task_id=$i");
});
}
// Wait all coroutine done
Barrier::wait($barrier);
$connection->send('All Task Done');
};// Task Server
$task = new Worker('http://0.0.0.0:8002');
$task->onMessage = function (TcpConnection $connection, Request $request) {
$task_id = $request->get('task_id');
$message = "Task $task_id Done";
echo $message . PHP_EOL;
$connection->close($message);
};Worker::runAll();
```### Parallel
Parallel executes multiple tasks concurrently and collects results. Use add to add tasks and wait to wait for completion and get results. Unlike Barrier, Parallel directly returns the results of each task.```php
eventLoop = Swoole::class; // Or Swow::class or Fiber::class
$worker->onMessage = function (TcpConnection $connection, Request $request) {
$parallel = new Parallel();
for ($i=1; $i<5; $i++) {
$parallel->add(function () use ($i) {
return file_get_contents("http://127.0.0.1:8002?task_id=$i");
});
}
$results = $parallel->wait();
$connection->send(json_encode($results)); // Response: ["Task 1 Done","Task 2 Done","Task 3 Done","Task 4 Done"]
};// Task Server
$task = new Worker('http://0.0.0.0:8002');
$task->onMessage = function (TcpConnection $connection, Request $request) {
$task_id = $request->get('task_id');
$message = "Task $task_id Done";
$connection->close($message);
};Worker::runAll();
```### Channel
Channel is a mechanism for communication between coroutines. One coroutine can push data into the channel, while another can pop data from it, enabling synchronization and data sharing between coroutines.
```php
eventLoop = Swoole::class; // Or Swow::class or Fiber::class
$worker->onMessage = function (TcpConnection $connection, Request $request) {
$channel = new Channel(2);
Coroutine::create(function () use ($channel) {
$channel->push('Task 1 Done');
});
Coroutine::create(function () use ($channel) {
$channel->push('Task 2 Done');
});
$result = [];
for ($i = 0; $i < 2; $i++) {
$result[] = $channel->pop();
}
$connection->send(json_encode($result)); // Response: ["Task 1 Done","Task 2 Done"]
};
Worker::runAll();
```### Pool
Pool is used to manage connection or resource pools, improving performance by reusing resources (e.g., database connections). It supports acquiring, returning, creating, and destroying resources.
```php
setConnectionCreator(function () use ($host, $port) {
$redis = new \Redis();
$redis->connect($host, $port);
return $redis;
});
$pool->setConnectionCloser(function ($redis) {
$redis->close();
});
$pool->setHeartbeatChecker(function ($redis) {
$redis->ping();
});
$this->pool = $pool;
}
public function get(): \Redis
{
return $this->pool->get();
}
public function put($redis): void
{
$this->pool->put($redis);
}
}// Http Server
$worker = new Worker('http://0.0.0.0:8001');
$worker->eventLoop = Swoole::class; // Or Swow::class or Fiber::class
$worker->onMessage = function (TcpConnection $connection, Request $request) {
static $pool;
if (!$pool) {
$pool = new RedisPool('127.0.0.1', 6379, 10);
}
$redis = $pool->get();
$redis->set('key', 'hello');
$value = $redis->get('key');
$pool->put($redis);
$connection->send($value);
};Worker::runAll();
```### Pool for automatic acquisition and release
```php
get();
Context::set('pdo', $pdo);
// When the coroutine is destroyed, return the connection to the pool
Coroutine::defer(function () use ($pdo) {
self::$pool->put($pdo);
});
}
return call_user_func_array([$pdo, $name], $arguments);
}
private static function initializePool(): void
{
self::$pool = new Pool(10);
self::$pool->setConnectionCreator(function () {
return new \PDO('mysql:host=127.0.0.1;dbname=your_database', 'your_username', 'your_password');
});
self::$pool->setConnectionCloser(function ($pdo) {
$pdo = null;
});
self::$pool->setHeartbeatChecker(function ($pdo) {
$pdo->query('SELECT 1');
});
}
}// Http Server
$worker = new Worker('http://0.0.0.0:8001');
$worker->eventLoop = Swoole::class; // Or Swow::class or Fiber::class
$worker->onMessage = function (TcpConnection $connection, Request $request) {
$value = Db::query('SELECT NOW() as now')->fetchAll();
$connection->send(json_encode($value));
};Worker::runAll();
```## Available commands
```php start.php start ```
```php start.php start -d ```
```php start.php status ```
```php start.php status -d ```
```php start.php connections```
```php start.php stop ```
```php start.php stop -g ```
```php start.php restart ```
```php start.php reload ```
```php start.php reload -g ```# Benchmarks
https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=plaintext&l=zik073-1r### Supported by
[](https://jb.gg/OpenSourceSupport)
## Other links with workerman
[webman](https://github.com/walkor/webman)
[AdapterMan](https://github.com/joanhey/AdapterMan)## Donate
PayPal## LICENSE
Workerman is released under the [MIT license](https://github.com/walkor/workerman/blob/master/MIT-LICENSE.txt).