swoole
注意
在 Swoole 内,无法通过 $_GET/$_POST/$_REQUEST/$_SESSION/$_COOKIE/$_SERVER
等 $_
开头的变量获取到任何属性参数。
快速启动TCP
实例化server对象,监听端口$server = new Swoole\Server('ip_address',port)
监听事件$server -> on('event',function(params){})
启动服务器$server->start()
快速启动UDP
实例化server对象$server = new Swoole\Server('ip_address',port,
SWOOLE_PROCESS, SWOOLE_SOCK_UDP);
- tips: udp无需链接,直接接收数据包
快速启动HTTP
$http = new Swoole\Http\Server('0.0.0.0',port);
- tips:HTTP 服务器只需要关注请求响应即可
- tips:使用 Chrome 浏览器访问服务器,会产生额外的一次请求,/favicon.ico,可以在代码中响应 404 错误。
- tips:应用程序可以根据 $request->server[‘request_uri’] 实现路由。
快速启动websocket 同tcp
MQTT(物联网,暂空)
异步执行任务(Task)
TCP服务实例
$serv = new Swoole\Server("127.0.0.1", 9501); //设置异步任务的工作进程数量
$serv->set(array('task_worker_num' => 4)); //此回调函数在worker进程中执行
$serv->on('receive', function($serv, $fd, $from_id, $data) { //投递异步任务
$task_id = $serv->task($data);
echo "Dispatch AsyncTask: id=$task_id\n";
}); //处理异步任务(此回调函数在task进程中执行)
$serv->on('task', function ($serv, $task_id, $from_id, $data) {
echo "New AsyncTask[id=$task_id]".PHP_EOL; //返回任务执行的结果
$serv->finish("$data -> OK");
}); //处理异步任务的结果(此回调函数在worker进程中执行)
$serv->on('finish', function ($serv, $task_id, $data) {
echo "AsyncTask[$task_id] Finish: $data".PHP_EOL;
});
$serv->start();
- tips:调用 $serv->task() 后,程序立即返回,继续向下执行代码。onTask 回调函数 Task 进程池内被异步执行。执行完成后调用 $serv->finish() 返回结果。
协程
go关键词创建一个协程,可以简单的理解为创建了一个线程
- 什么是协程
协程可理解为线程,但为用户态,无法使用多核cpu
- 什么是channel
消息队列,协程间通讯,但无法跨进程通讯
- 什么是协程容器
使用 Coroutine::create
或 go
方法创建协程,在创建的协程中才能使用协程 API,而协程必须创建在协程容器里面。
- 协程调度
决定到底让 CPU 执行哪个协程的代码决断过程就是协程调度
- 什么是EventLoop
事件循环,要发生事件的句柄加入到epoll_wait
中,epoll_wait
函数返回的时候我们就会挨个调用相应的回调函数,叫做一轮事件循环,即 IO 多路复用,然后再次阻塞调用 epoll_wait
进行下一轮事件循环。
服务器(异步)
Swoole\Server
类是所有异步风格服务器的基类
- 什么是IPC
同一台主机上两个进程间通信,在 Swoole 下使用了 2 种方式 Unix Socket 和 sysvmsg,主要为Unix Socket方式
Unix Socket又可分两种,类似TCP
和UDP
TCP/UDP服务器
属性
$setting
Server::set()
函数设置的参数会保存到$server -> $setting
属性上,在回调函数中可以访问运行参数的值$master_pid
返回当前服务器主进程PID
,只能在onStart/onWorkerStart
后获取
$manager_pid
返回当前服务器管理进程的PID
,只能在onStart/onWorkerStart
后获取
$workder_id
得到当前 Worker
进程的编号,包括Task进程
- 提示
- 这个属性与
onWorkerStart
时的$workerId
是相同的。 - Worker 进程编号范围是
[0, $serv->setting['worker_num']-1]
- Task 进程编号范围是
[$serv->setting['worker_num'], $serv->setting['worker_num'] + $serv->setting['task_worker_num']]
- 工作进程重启后
worker_id
的值是不变的
$worker_pid
得到当前Worker
进程的操作系统进程ID
。与posix_getpid()
返回值相同
$taskwoker
当前进程是否是Task
进程
- 返回值:
- 返回值为true,表示为Task工作进程
- 返回值为false,表示为Worker进程
$connections
TCP
连接迭代器,可使用foreach
遍历服务器当前所有连接,遍历的元素为单个连接的fd
tips:
$connections
是一个迭代器对象,不是php数组,所以只能使用foreach
进行遍历操作$ports
监听端口数组,如果服务器监听了多个端口,可以遍历Server::$ports
得到所有Swoole\Server\Port
对象
其中 swoole_server::$ports[0] 为构造方法所设置的主服务器端口。
方法
__construct
初始化方法set
设置运行时参数on
注册事件回调函数addListener
增加监听端口(别名listen
)addProcess
增加用户自定义工作进程start
启动服务reload
重启所有worker/task
进程(柔性终止/重启),对自定义工作进程无效stop
停止当前woker
进程,并立即触发onWorkerStop
回调shutdown
关闭服务tick
添加定时器(间隔时间 毫秒),可自定义回调函数after
一次性定时器defer
延后执行一个函数clearTimer
清除tick/after
定时器close
关闭客户端连接send
向客服端发送数据(有长度限制)sendfile
发送文件到TCP客户端连接sendto
向任意客户端发送IP:PORT
发送UDP
数据包sendwait
同步地向客户端发送数据sendMessage
向任意worker
进程或者task
进程发送消息,在飞主进程和管理进程中可调用exist
检测fd
对应的连接是否存在pause
停止接收数据(指定fd
)resume
恢复接收数据getClientInfo
获取连接信息getClientList
遍历当前server
所有客户端连接,基于共享内存bind
将连接绑定到一个用户定义的UID
stats
得到当前server
的活动TCP
连接数,启动时间,accept/close
的总次数等信息task
投递一个异步任务到task_worker
池中,此函数是非阻塞的,执行完毕会立即返回。taskwait
同投递一个异步任务到task进程池去执行,但此函数是同步等待,知道任务完成或者超时返回taskWaitMulti
并发执行多个task异步任务,不支持协程调度taskCo
并发执行task
并进行协程调度,为协程环境下的上个函数的功能finish
用于在task进程中通知worker进程,投递的任务已完成,此函数可传递结果数据给worker进程heartbeat
主动监测服务器所有连接,并找出已经超过约定时间的连接getLastError
获取最近一次操作错误的错误码。业务代码中可以根据错误码类型执行不同逻辑getSocket
得到底层的socket
句柄,返回对象为sockets
资源句柄protect
设置客户端连接为保护状态,不被心跳线程切断confirm
确认连接。当客户端建立连接后,并不监听可读时间,仅触发onConnect
事件回调,在onConnect
回调中执行confirm
确认连接,这时服务器才会监听可读事件,接收来自客户端连接的数据
配置
reactor_num
设置启动的Reactor
线程数woker_num
设置启动的Worker
进程数max_request
设置worker
进程的最大任务数max_conn
服务器程序,最大允许的连接数task_worker_num
配置task进程
的数量(未配置不启动task)task_ipc_mode
设置task进程
与worker
进程之间的通信方式task_max_request
设置task进程的最大任务数(设置 task 进程的最大任务数。一个 task 进程在处理完超过此数值的任务后将自动退出。这个参数是为了防止 PHP 进程内存溢出。如果不希望进程自动退出可以设置为 0。)task_tmpdir
设置task的数据临时目录task_enable_coroutine
开启task
协程支持task_use_object
使用面向对象风格的task回调格式dispatch_mode
数据包分发策略dispatch_func
自定义dispatch_mode
,使用c++
函数或者php
函数message_queue_key
设置消息队列的KEY
(仅在 task_ipc_mode = 2/3 时使用)daemonize
守护进程化(设置daemonize => 1
时,程序将转入后台作为守护进程运行。长时间运行的服务器端程序必须启用此项。如果不启用守护进程,当 ssh 终端退出后,程序将被终止运行。)backlog
设置Listen
队列长度,决定最多同时有多少个等待accept
的连接log_file
指定Swoole
错误日志文件log_level
设置Server
错误日志打印的等级,范围是0~6
。低于设置的日志信息不会抛出
事件
每个回调函数都是一个php函数,对应一个事件
onStart
启动后在主进程的主线程回调此函数(此回调中,只允许echo
、打印Log
、修改进程名称)onShutdown
此事件在Server
正常结束时发生(在其中不能调用任何一部或协程相关API)onWorkerStart
在worker进程/ task进程启动时发生,此处创建的对象可在进程生命周期内使用(在onWorkerStart
回调函数中会自动创建协程,所以可以调用协程API
)onWorkerStop
此事件在worker进程终止时发生,在此函数中可以收回woker进程申请的各类资源onWorkerExit
onConnect
有新的连接进入时,在worker进程中回调onReceive
接收到数据时回调此函数,发生在worker进程中onPacke
接收到UDP数据包时回调此函数,发生在worker进程中onClose
TCP客户端连接关闭后,在worker进程中回调此函数onTask
在task进程内被调用。worker进程可以使用atsk函数向task_worker
进程投递新的任务。当前的task进程在调用ontask
回调函数时会将进程状态切换为忙碌,这时将不会接收新的task,当ontask
函数返回时会将进程状态切换为空闲然后继续接收新的task。onFinish
此回调函数在worker进程被调用,当worker进程投递的任务在task进程中完成时,task进程会通过Swoole\Server->finish()
方法将任务处理的结果发送给worker进程onPipeMessage
当工作进程收到由$server->sendMessage()
发送的unixSocket
消息时会触发onPipeMessage
事件。worker/task
进程都可能回触发onPipeMessage
事件onWorkerError
当woeker/task
进程发生异常后会在Manager
进程内回调此函数onManagerStart
当管理进程启动时触发此事件onManagerStop
当管理进程结束时触发onBeforeReload
worker进程Reload
之前触发此事件,在Manager进程中回调onAfterReload
worker进程Reload
之后触发此事件,在Manager进程中回调
事件执行顺序
- 所有事件回调均在
$server->start()
后发生 - 服务器关闭程序终止时最后一次事件是
onShutdown
- 服务器启动成功后,
onStart/onManagerStart/onWorkerStart
会在不同的进程内并发执行 onReceive/onConnect/onClose
在 Worker进程中触发Worker/Task
进程启动、结束时会分别调用一次onWorkerStart/onWorkerStop
- onTask 事件仅在task进程中发生
- onFinish 事件仅在 worker 进程中发生
onStart/onManagerStart/onWorkerStart
3个事件的执行顺序是不确定的