• 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的基本用法(示例详解)的详细内容

  • 相关阅读:
    【1431】java学习网站系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
    maven多模块依赖包程序包xxx不存在
    Linux 命令:PS(进程状态)
    c语言---指针
    使用域名转发mqtt协议,避坑指南
    《Python+Kivy(App开发)从入门到实践》自学笔记:简单UX部件——Image图片
    【第三方登录】微信web扫一扫登录步骤
    使用GBase 8s数据库
    java异常处理
    朝夕光年「红砖」搭建平台架构设计和应用落地
  • 原文地址:https://blog.csdn.net/weixin_64051447/article/details/133675743