Swoole入门

简介

是什么?

Swoole是一个PHP扩展,使用纯C语言编写。

Swoole内置了Http/WebSocket服务器端/客户端、Http2.0服务器端。

Swoole支持AsyncTask,消息队列,毫秒定时器,异步文件读写等功能。

Swoole从2.0版本开始支持了内置协程,可以使用完全同步的代码实现异步程序。PHP代码无需额外增加任何关键词,底层自动进行协程调度,实现异步。

Swoole可以广泛应用于互联网、移动通信、企业软件、网络游戏、物联网、车联网、智能家庭等领域。

版本选择

建议使用的版本:

稳定版:v1.9.23

预览版:v2.0.12

1.9.x分支已进入特性锁定期,不再开发新功能,仅修复BUG。

建议使用的PHP版本:

PHP5.5或更高版本

PHP7.0.13或更高版本

可以免费使用吗

Swoole是开源免费的自由软件,授权协议是Apache2.0。企业和个人开发者均可免费使用Swoole的代码,并且在Swoole之上所作的修改可用于商业产品,无需开源(注:必须保留原作者的版权声明)。

实例讲解

HttpServer

swoole内置Http服务器的支持。swoole版的http server相对于php-fpm,最大优势在于高性能:代码一次载入内存,后续无需再解释执行。缺点是调试没有nginx+php-fpm方便。

使用swoole,通过几行代码即可写出一个异步非阻塞多进程的Http服务器:

$server=newswoole_http_server("0.0.0.0",9051);

$server->set(['daemonize'=>false,//是否后台运行'log_file'=>'swoole.log',

]);

$server->on('Start',function(){swoole_set_process_name("swoole_http_server");echo"Start\n";

});

$server->on('Request',function($request,$response){

print_r($request->get);// print_r($request->post);// print_r($request->cookie);// print_r($request->files);// print_r($request->header);// print_r($request->server);$response->cookie("User","Swoole");$response->header("X-Server","Swoole");$response->end("Hello Swoole!");

});

$server->start();

swoole_http_server继承自swoole_server,是一个完整的http服务器实现。

注意:swoole_http_server对Http协议的支持并不完整,建议仅作为应用服务器。并且在前端增加Nginx作为代理:

server{root /data/wwwroot/;server_name local.swoole.com;location /{proxy_http_version 1.1;proxy_set_header Connection"keep-alive";proxy_set_header X-Real-IP$remote_addr;if(!-e$request_filename){proxy_pass http://127.0.0.1:9501;}}}WebSocketServer

swoole增加了内置的WebSocket服务器支持,通过几行PHP代码就可以写出一个异步非阻塞多进程的WebSocket服务器。

$server=newswoole_websocket_server("0.0.0.0",9052);

$server->on('Start',function(swoole_websocket_server$server){swoole_set_process_name("swoole_websocket_server");echo"Server Start...\n";

});

$server->on('WorkerStart',function(swoole_websocket_server$server,$worker_id){if($server->worker_id==){swoole_timer_tick(2000,function($timer_id){//2000msecho"tick-2000ms\n";});}});

$server->on('Open',function(swoole_websocket_server$server,$request){echo"server: handshake success with fd:{$request->fd}\n";

});

$server->on('Message',function(swoole_websocket_server$server,$frame){echo"receive from fd:{$frame->fd}:{$frame->data}\n";$server->push($frame->fd,"Hello fd:{$frame->fd}, I'm Server.\n");

});

$server->on('Close',function($ser,$fd){echo"client fd:{$fd}closed\n";

});

$server->start();WebSocket客户端

最简单的是使用JS编写:

socket=newWebSocket('ws://192.168.99.100:9052/');socket.onopen=function(evt){// 发送一个初始化消息socket.send('I am the client and I\'m listening!');};// 监听消息socket.onmessage=function(event){console.log('Received a message: ',event.data);alert(event.data);};// 监听Socket的关闭socket.onclose=function(event){console.log('Socket has closed',event);};socket.onerror=function(evt){console.log('onerror',event);};

进程模型

我们来使用实例进行分析:

$server=new\swoole_server("0.0.0.0",9053);//tcp_server

$server->set(['daemonize'=>false,//是否后台运行'log_file'=>'swoole.log',// 'worker_num' => 2,

]);

$server->on('connect',function($serv,$fd){echo"client connect. fd is{$fd}\n";

});

$server->on('receive',function($serv,$fd,$from_id,$data){echo"client connect. fd is{$fd}\n";

});$server->on('close',function($serv,$fd){echo"client close. fd is{$fd}\n";

});

// 以下回调发生在Master进程

$server->on("start",function(\swoole_server$server){echo"On master start.\n";

});$server->on('shutdown',function(\swoole_server$server){echo"On master shutdown.\n";

});

// 以下回调发生在Manager进程

$server->on('ManagerStart',function(\swoole_server$server){echo"On manager start.\n";

});

$server->on('ManagerStop',function(\swoole_server$server){echo"On manager stop.\n";

});// 以下回调也发生在Worker进程$server->on('WorkerStart',function(\swoole_server$server,$worker_id){echo"Worker start\n";

});

$server->on('WorkerStop',function(\swoole_server$server,$worker_id){echo"Worker stop\n";

});

$server->on('WorkerError',function(\swoole_server$server,$worker_id,$worker_pid,$exit_code){echo"Worker error\n";

});

$server->start();

我们使用 查看swoole进程数:

[root@9355490fe5da /]# pstree -ap 235

php,235 tcp_server.php

|-php,236 tcp_server.php

||-php,239 tcp_server.php

|`-php,240 tcp_server.php

发现有4个进程。按PID从小到大分别是 进程、进程、进程(2个)。

基于此,我们简单梳理一下,当执行的start方法之后,发生了什么:

守护进程模式下,当前进程fork出Master进程,然后退出,Master进程触发OnMasterStart事件。

Master进程启动成功之后,fork出Manager进程,并触发OnManagerStart事件。

Manager进程启动成功时候,fork出Worker进程,并触发OnWorkerStart事件。

非守护进程模式下,则当前进程直接作为Master进程工作。

所以,一个最基础的Swoole Server,至少需要有3个进程,分别是Master进程、Manager进程和Worker进程。

事实上,一个多进程模式下的Swoole Server中,有且只有一个Master进程;有且只有一个Manager进程;却可以有n个Worker进程。

Master进程是一个多线程进程,其中有一组非常重要的线程,叫做Reactor线程(组)。

每当一个客户端连接上服务器的时候,都会由Master进程从已有的Reactor线程中,根据一定规则挑选一个,专门负责向这个客户端提供维持链接、处理网络IO与收发数据等服务。

Manager进程,某种意义上可以看做一个代理层。

它本身并不直接处理业务,其主要工作是将Master进程中收到的数据转交给Worker进程,或者将Worker进程中希望发给客户端的数据转交给Master进程进行发送。

Manager进程还负责监控Worker进程,如果Worker进程因为某些意外挂了,Manager进程会重新拉起新的Worker进程。

Worker进程其实就是处理各种业务工作的进程,Manager将数据包转交给Worker进程,然后Worker进程进行具体的处理,并根据实际情况将结果反馈给客户端。

参考资料

官网:https://www.swoole.com/

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180325G08IWM00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励