• workerman的基本用法(示例详解)


    workerman是什么?

    Workerman是一个异步事件驱动PHP框架,具有高性能,可轻松构建快速,可扩展的网络应用程序。支持HTTP,Websocket,SSL和其他自定义协议。支持libevent,HHVM,ReactPHP。

    要求

    • PHP 5.3或更高版本
    • 兼容POSIX的操作系统(Linux,OSX,BSD)
    • 用于PHP的POSIX和PCNTL扩展

    安装

    composer require workerman/workerman

    基本用法

    websocket服务器

    1. require_once __DIR__ . '/vendor/autoload.php';
    2. use Workerman\Worker;
    3. // 创建一个Websocket服务器
    4. $ws_worker = new Worker("websocket://0.0.0.0:2346");
    5. $ws_worker->count = 4;
    6. // 在新连接到来时发出
    7. $ws_worker->onConnect = function($connection)
    8. {
    9. echo "New connection\n";
    10. };
    11. // 接收数据时发出
    12. $ws_worker->onMessage = function($connection, $data)
    13. {
    14. // Send hello $data
    15. $connection->send('hello ' . $data);
    16. };
    17. // 连接关闭时发出
    18. $ws_worker->onClose = function($connection)
    19. {
    20. echo "Connection closed\n";
    21. };
    22. // 运行worker
    23. Worker::runAll();

    http服务器

    1. require_once __DIR__ . '/vendor/autoload.php';
    2. use Workerman\Worker;
    3. // #### http worker ####
    4. $http_worker = new Worker("http://0.0.0.0:2345");
    5. $http_worker->count = 4;
    6. // 接收数据时发出
    7. $http_worker->onMessage = function($connection, $data)
    8. {
    9. //$_GET、$_POST、$_COOKIE、$_SESSION、$_SERVER、$_FILES都是可用的
    10. var_dump($_GET, $_POST, $_COOKIE, $_SESSION, $_SERVER, $_FILES);
    11. // 发送数据给客户端
    12. $connection->send("hello world \n");
    13. };
    14. // 运行所有workers
    15. Worker::runAll();

    WebServer

    1. require_once __DIR__ . '/vendor/autoload.php';
    2. use Workerman\WebServer;
    3. use Workerman\Worker;
    4. // WebServer
    5. $web = new WebServer("http://0.0.0.0:80");
    6. $web->count = 4;
    7. $web->addRoot('www.your_domain.com', '/your/path/Web');
    8. $web->addRoot('www.another_domain.com', '/another/path/Web');
    9. Worker::runAll();

    TCP服务器

    1. require_once __DIR__ . '/vendor/autoload.php';
    2. use Workerman\Worker;
    3. // #### 创建socket并监听1234端口 ####
    4. $tcp_worker = new Worker("tcp://0.0.0.0:1234");
    5. $tcp_worker->count = 4;
    6. //在新连接到来时发出
    7. $tcp_worker->onConnect = function($connection)
    8. {
    9. echo "New Connection\n";
    10. };
    11. // 接收数据时发出
    12. $tcp_worker->onMessage = function($connection, $data)
    13. {
    14. // 发送数据给客户端
    15. $connection->send("hello $data \n");
    16. };
    17. // 在新连接到来时发出
    18. $tcp_worker->onClose = function($connection)
    19. {
    20. echo "Connection closed\n";
    21. };
    22. Worker::runAll();

    启用SSL

    1. require_once __DIR__ . '/vendor/autoload.php';
    2. use Workerman\Worker;
    3. // SSL环境
    4. $context = array(
    5. 'ssl' => array(
    6. 'local_cert' => '/your/path/of/server.pem',
    7. 'local_pk' => '/your/path/of/server.key',
    8. 'verify_peer' => false,
    9. )
    10. );
    11. // 创建一个带有ssl的Websocket服务器。
    12. $ws_worker = new Worker("websocket://0.0.0.0:2346", $context);
    13. // 启用SSL。WebSocket+SSL意味着安全的WebSocket (wss://)。
    14. //类似的Https方法等等。
    15. $ws_worker->transport = 'ssl';
    16. $ws_worker->onMessage = function($connection, $data)
    17. {
    18. // 发送hello $data
    19. $connection->send('hello ' . $data);
    20. };
    21. Worker::runAll();

    自定义协议

    Protocols/MyTextProtocol.php

    1. namespace Protocols;
    2. /**
    3. * 用户定义的协议
    4. *格式文本+“\ n”
    5. */
    6. class MyTextProtocol
    7. {
    8. public static function input($recv_buffer)
    9. {
    10. // 找到“\n”第一个出现的位置
    11. $pos = strpos($recv_buffer, "\n");
    12. // 不是一个完整的package。返回0,因为package的长度无法计算
    13. if($pos === false)
    14. {
    15. return 0;
    16. }
    17. // 返回package的长度
    18. return $pos+1;
    19. }
    20. public static function decode($recv_buffer)
    21. {
    22. return trim($recv_buffer);
    23. }
    24. public static function encode($data)
    25. {
    26. return $data."\n";
    27. }
    28. }

    1. require_once __DIR__ . '/vendor/autoload.php';
    2. use Workerman\Worker;
    3. // #### MyTextProtocol worker ####
    4. $text_worker = new Worker("MyTextProtocol://0.0.0.0:5678");
    5. $text_worker->onConnect = function($connection)
    6. {
    7. echo "New connection\n";
    8. };
    9. $text_worker->onMessage = function($connection, $data)
    10. {
    11. // 发送数据给客户端
    12. $connection->send("hello world \n");
    13. };
    14. $text_worker->onClose = function($connection)
    15. {
    16. echo "Connection closed\n";
    17. };
    18. // 运行所有workers
    19. Worker::runAll();

    计时器

    1. require_once __DIR__ . '/vendor/autoload.php';
    2. use Workerman\Worker;
    3. use Workerman\Lib\Timer;
    4. $task = new Worker();
    5. $task->onWorkerStart = function($task)
    6. {
    7. // 2.5
    8. $time_interval = 2.5;
    9. $timer_id = Timer::add($time_interval,
    10. function()
    11. {
    12. echo "Timer run\n";
    13. }
    14. );
    15. };
    16. //运行
    17. Worker::runAll();

    AsyncTcpConnection(tcp / ws / text / frame等...)

    1. require_once __DIR__ . '/vendor/autoload.php';
    2. use Workerman\Worker;
    3. use Workerman\Connection\AsyncTcpConnection;
    4. $worker = new Worker();
    5. $worker->onWorkerStart = function()
    6. {
    7. //客户端Websocket协议。
    8. $ws_connection = new AsyncTcpConnection("ws://echo.websocket.org:80");
    9. $ws_connection->onConnect = function($connection){
    10. $connection->send('hello');
    11. };
    12. $ws_connection->onMessage = function($connection, $data){
    13. echo "recv: $data\n";
    14. };
    15. $ws_connection->onError = function($connection, $code, $msg){
    16. echo "error: $msg\n";
    17. };
    18. $ws_connection->onClose = function($connection){
    19. echo "connection closed\n";
    20. };
    21. $ws_connection->connect();
    22. };
    23. Worker::runAll();

    ReactPHP的异步Mysql

    composer require react/mysql

    1. require_once __DIR__ . '/vendor/autoload.php';
    2. use Workerman\Worker;
    3. $worker = new Worker('tcp://0.0.0.0:6161');
    4. $worker->onWorkerStart = function() {
    5. global $mysql;
    6. $loop = Worker::getEventLoop();
    7. $mysql = new React\MySQL\Connection($loop, array(
    8. 'host' => '127.0.0.1',
    9. 'dbname' => 'dbname',
    10. 'user' => 'user',
    11. 'passwd' => 'passwd',
    12. ));
    13. $mysql->on('error', function($e){
    14. echo $e;
    15. });
    16. $mysql->connect(function ($e) {
    17. if($e) {
    18. echo $e;
    19. } else {
    20. echo "connect success\n";
    21. }
    22. });
    23. };
    24. $worker->onMessage = function($connection, $data) {
    25. global $mysql;
    26. $mysql->query('show databases' /*trim($data)*/, function ($command, $mysql) use ($connection) {
    27. if ($command->hasError()) {
    28. $error = $command->getError();
    29. } else {
    30. $results = $command->resultRows;
    31. $fields = $command->resultFields;
    32. $connection->send(json_encode($results));
    33. }
    34. });
    35. };
    36. Worker::runAll();

    ReactPHP的Async Redis

    composer require clue/redis-react

    1. require_once __DIR__ . '/vendor/autoload.php';
    2. use Clue\React\Redis\Factory;
    3. use Clue\React\Redis\Client;
    4. use Workerman\Worker;
    5. $worker = new Worker('tcp://0.0.0.0:6161');
    6. $worker->onWorkerStart = function() {
    7. global $factory;
    8. $loop = Worker::getEventLoop();
    9. $factory = new Factory($loop);
    10. };
    11. $worker->onMessage = function($connection, $data) {
    12. global $factory;
    13. $factory->createClient('localhost:6379')->then(function (Client $client) use ($connection) {
    14. $client->set('greeting', 'Hello world');
    15. $client->append('greeting', '!');
    16. $client->get('greeting')->then(function ($greeting) use ($connection){
    17. // Hello world!
    18. echo $greeting . PHP_EOL;
    19. $connection->send($greeting);
    20. });
    21. $client->incr('invocation')->then(function ($n) use ($connection){
    22. echo 'This is invocation #' . $n . PHP_EOL;
    23. $connection->send($n);
    24. });
    25. });
    26. };
    27. Worker::runAll();

    Aysnc dns的ReactPHP

    composer require react/dns

    1. require_once __DIR__ . '/vendor/autoload.php';
    2. use Workerman\Worker;
    3. $worker = new Worker('tcp://0.0.0.0:6161');
    4. $worker->onWorkerStart = function() {
    5. global $dns;
    6. // Get event-loop.
    7. $loop = Worker::getEventLoop();
    8. $factory = new React\Dns\Resolver\Factory();
    9. $dns = $factory->create('8.8.8.8', $loop);
    10. };
    11. $worker->onMessage = function($connection, $host) {
    12. global $dns;
    13. $host = trim($host);
    14. $dns->resolve($host)->then(function($ip) use($host, $connection) {
    15. $connection->send("$host: $ip");
    16. },function($e) use($host, $connection){
    17. $connection->send("$host: {$e->getMessage()}");
    18. });
    19. };
    20. Worker::runAll();

    ReactPHP的Http客户端

    composer require react/http-client

    1. require_once __DIR__ . '/vendor/autoload.php';
    2. use Workerman\Worker;
    3. $worker = new Worker('tcp://0.0.0.0:6161');
    4. $worker->onMessage = function($connection, $host) {
    5. $loop = Worker::getEventLoop();
    6. $client = new \React\HttpClient\Client($loop);
    7. $request = $client->request('GET', trim($host));
    8. $request->on('error', function(Exception $e) use ($connection) {
    9. $connection->send($e);
    10. });
    11. $request->on('response', function ($response) use ($connection) {
    12. $response->on('data', function ($data) use ($connection) {
    13. $connection->send($data);
    14. });
    15. });
    16. $request->end();
    17. };
    18. Worker::runAll();

    ReactPHP的ZMQ

    composer require react/zmq

    1. require_once __DIR__ . '/vendor/autoload.php';
    2. use Workerman\Worker;
    3. $worker = new Worker('text://0.0.0.0:6161');
    4. $worker->onWorkerStart = function() {
    5. global $pull;
    6. $loop = Worker::getEventLoop();
    7. $context = new React\ZMQ\Context($loop);
    8. $pull = $context->getSocket(ZMQ::SOCKET_PULL);
    9. $pull->bind('tcp://127.0.0.1:5555');
    10. $pull->on('error', function ($e) {
    11. var_dump($e->getMessage());
    12. });
    13. $pull->on('message', function ($msg) {
    14. echo "Received: $msg\n";
    15. });
    16. };
    17. Worker::runAll();

    react的STOMP

    composer requirereact/stomp

    1. require_once __DIR__ . '/vendor/autoload.php';
    2. use Workerman\Worker;
    3. $worker = new Worker('text://0.0.0.0:6161');
    4. $worker->onWorkerStart = function() {
    5. global $client;
    6. $loop = Worker::getEventLoop();
    7. $factory = new React\Stomp\Factory($loop);
    8. $client = $factory->createClient(array('vhost' => '/', 'login' => 'guest', 'passcode' => 'guest'));
    9. $client
    10. ->connect()
    11. ->then(function ($client) use ($loop) {
    12. $client->subscribe('/topic/foo', function ($frame) {
    13. echo "Message received: {$frame->body}\n";
    14. });
    15. });
    16. };
    17. Worker::runAll();

    可用命令

    1. php start.php start
    2. php start.php start -d

    2f960202310071039557166.png

    php start.php status [object Object]

    1. php start.php connections
    2. php start.php stop
    3. php start.php restart
    4. php start.php reload

    基准

    1. CPU: Intel(R) Core(TM) i3-3220 CPU @ 3.30GHz and 4 processors totally
    2. Memory: 8G
    3. OS: Ubuntu 14.04 LTS
    4. Software: ab
    5. PHP: 5.5.9

    代码

    1. use Workerman\Worker;
    2. $worker = new Worker('tcp://0.0.0.0:1234');
    3. $worker->count=3;
    4. $worker->onMessage = function($connection, $data)
    5. {
    6. $connection->send("HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nServer: workerman\r\nContent-Length: 5\r\n\r\nhello");
    7. };
    8. Worker::runAll();

    结果

    1. ab -n1000000 -c100 -k http://127.0.0.1:1234/
    2. This is ApacheBench, Version 2.3 <$Revision: 1528965 $>
    3. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
    4. Licensed to The Apache Software Foundation, http://www.apache.org/
    5. Benchmarking 127.0.0.1 (be patient)
    6. Completed 100000 requests
    7. Completed 200000 requests
    8. Completed 300000 requests
    9. Completed 400000 requests
    10. Completed 500000 requests
    11. Completed 600000 requests
    12. Completed 700000 requests
    13. Completed 800000 requests
    14. Completed 900000 requests
    15. Completed 1000000 requests
    16. Finished 1000000 requests
    17. Server Software: workerman/3.1.4
    18. Server Hostname: 127.0.0.1
    19. Server Port: 1234
    20. Document Path: /
    21. Document Length: 5 bytes
    22. Concurrency Level: 100
    23. Time taken for tests: 7.240 seconds
    24. Complete requests: 1000000
    25. Failed requests: 0
    26. Keep-Alive requests: 1000000
    27. Total transferred: 73000000 bytes
    28. HTML transferred: 5000000 bytes
    29. Requests per second: 138124.14 [#/sec] (mean)
    30. Time per request: 0.724 [ms] (mean)
    31. Time per request: 0.007 [ms] (mean, across all concurrent requests)
    32. Transfer rate: 9846.74 [Kbytes/sec] received
    33. Connection Times (ms)
    34. min mean[+/-sd] median max
    35. Connect: 0 0 0.0 0 5
    36. Processing: 0 1 0.2 1 9
    37. Waiting: 0 1 0.2 1 9
    38. Total: 0 1 0.2 1 9
    39. Percentage of the requests served within a certain time (ms)
    40. 50% 1
    41. 66% 1
    42. 75% 1
    43. 80% 1
    44. 90% 1
    45. 95% 1
    46. 98% 1
    47. 99% 1
    48. 100% 9 (longest request)

    以上就是workerman的基本用法(示例详解)的详细内容

  • 相关阅读:
    《数据库的原理与应用》--用两种方法实现S-T数据库创建
    双非鼠鼠保研寄
    摇骰子、抽奖转盘酒桌游戏 人生重启模拟器小程序源码分享-开通流量主躺着赚钱
    [二进制学习笔记]LibcSearcher报错no matched libc
    数据的4个等级
    协程的创建
    ABAP:ME28/ME2L/ME2N标准报表字段增强统一出口
    分组背包问题
    028.Python面向对象_类&补充_元类
    【开课预告】下半年软考(中/高级)认证将于8月20日开班
  • 原文地址:https://blog.csdn.net/weixin_64051447/article/details/133675743