方法太多, 接前面 swoole学习之: 服务端(异步风格)-TCP/UDP服务器 - Swoole\Server的方法, 继续敲....
reload(): 安全地重启所有 Worker/Task 进程
Swoole\Server->reload(bool $only_reload_taskworker = false): bool
- bool $only_reload_taskworker: 是否仅重启task进程
reload 有保护机制,当一次 reload 正在进行而未结束时, 再次发送reload指令会被丢弃
注意:
- 平滑重启只对
onWorkerStart
或onReceive
等在Worker进程中include/require
的PHP文件有效 - 对
Server
启动前就已经引入的PHP文件无效 - 对于
Server
的配置,即$server->set()
中传入的参数, 必须重启整个server Server
可以监听一个内网端口, 然后接收远程的控制命令来重启所有Worker
进程
Stop(): 停止当前Worker进程并立即触发onWorkerStop回调
Swoole\Server->stop(int $workerId = -1, bool $waitEvent = false): bool
- $workerId: 指定
worker id
- $waitEvent: 退出策略, false表示立即退出(不等待时间循环结束), true表示等待事件循环结束
设置
waitEvent=true
后, 底层会使用异步安全重启策略: 先通知Manager进程, 然后重新启动一个新的Worker
进程来处理新的请求, 指定的那个旧的Worker
会等待事件, 直到事件循环为空或超过max_wait_time
后退出进程
shutown(): 关闭服务
Swoole\Server->shutdown(): void
- 此函数可以用在
Worker
进程内 - kill进程, 即向主进程发送SIGTERM(信息编号为15)也可以关闭服务:
kill -15 主进程pid
使用 kill -l 命令列出所有可用信号, 最常用的信号是:
- 1 (SIGHUP): 重新加载进程
- 9 (SIGKILL): 杀死一个进程
- 15 (SIGTERM): 正常停止一个进程
tick(): 添加定时器
Swoole\Timer::tick
的别名. 可以自定义回调函数.
Swoole\Server->tick(int $millisecond, mixed $callback):void
- millisecond: 间隔时间, 单位: 毫秒(千分之一秒)
- callback: 回调函数, 可以是函数名称, 静态方法名, 或者闭包函数 注意:
Worker
进程结束后, 所有定时器都会自动销毁tick/after
定时器不能在Server->start
之前使用
$server = new Swoole\Server('127.0.0.1', 9502);
//在onWorkerStart中使用: 启动后每隔1s在服务端打印一次信息
$server->on('workerstart', function($server, $workerId){
if(!$server->taskworker){
$server->tick(1000, function($id){
echo 'id: '.$id.', time is:'.date('Y-m-d H:i:s').PHP_EOL;
});
}else{
$server->tick(1000);
}
});
//在OnReceive中使用: 接收到一次数据之后, 会每个1s向客户端发送一次信息
$server->on('Receive', function($server, $fd, $reactor_id, $data){
//$reactor_id: TCP连接所在的Reactor线程ID, int
echo date('Y-m-d H:i:s').' Client '.$fd.' send message: '.trim($data).PHP_EOL;
$server->tick(1000, function()use($server, $fd, $reactor_id){
$server->send($fd, 'Hello, your id:'.$fd.', reactor_id:'.$reactor_id.', time is:'.date('Y-m-d H:i:s').PHP_EOL);
});
});
//启动服务
$server->start();
after(): 添加一个一次性定时器
Swoole\Timer::after
的别名. 这个一次性定时器执行完成后即自行销毁.
Swoole'Server->after(int $millisecond, mixed $callback);
注意: callback函数不接受任何参数, but WHY?
defer(): 延后执行一个函数
Event::defer的别名
Swoole\Server->defer(callable $callback): void
- callback: 可以是可执行的函数变量、字符串、数组、匿名(闭包)函数
注意:
- 底层会再EventLoop循环完成后执行此函数. 此函数的目的是为了让一些PHP代码延后执行,程序优先处理其他的IO事件.比如, 某个回调函数有cpu密集计算而又不是很着急,可以让进程处理完其他的事件再去进行cpu密集计算.
- 底层不保证defer的函数会立即执行. 如果是系统关键逻辑, 需要尽快执行, 请使用after定时器实现
- 在onWorkerStart回调中执行defer时, 必须等到有事件发生才会回调
e.g:
function dbQuery($server, $db){
$server->defer(function() use ($db){
$db->close();
});
}
clearTimer(): 清除 tick\after的定时器
Swoole\Timer::clear
的别名, 用于清除由tick,after建立的定时器.
Swoole\Server->clearTimer(int $timerId): bool
clearTimer仅可用于清除当前进程的定时器
e.g:
$timerId = $server->tick(function($id) use($server){
$server->clearTimer($id);//$id是定时器的id
};
close(): 关闭客户端连接
Swoole\Server->close(int $fd, bool $reset=false): bool
- $fd: 指定要关闭的tcp连接的文件描述符,在swoole_server中是客户端的唯一标识符
- $reset: 为true会强制关闭连接, 并丢弃发送队列中的数据 注意:
Server
主动close
连接, 或者客户端close
连接, 都会触发onClose
事件- 不要在
close
之后写相关的数据清理逻辑, 应当放置到onClose
回调中处理 HTTP\Server
的fd
在上层回调方法的response
对象中获取 e.g:
$server->on('request', function($request, $response) use ($server) {
$fd = $request->fd;//获取fd
$server->send($fd, 'Server closed your connection').PHP_EOL;
$server->close($fd);
})
send(): 向客户端发送数据
Swoole\Server->send(int $fd, string $data, int $serverSocket=-1): bool
- int $fd: 客户端连接的唯一标识
- string $data: 要发送的数据
- int $serverSocket: 向UnixSocketDGRAM对端发送数据时需要此项参数, TCP客户端不需要填写
发送过程是异步的, 底层会自动监听客户端, 将数据逐步发送给客户端, 也就是说不是服务端send之后客户端立马就能收到数据了
- 安全性
- send操作具有
原子性
, 多个进程同时调用send给向同一个TCP连接发送数据,不会发生数据混乱
- send操作具有
- 长度限制
- 如果数据大小超过2M, 应将文件写入临时文件, 然后通过
sendfile
接口进行发送 - 通过设置
buffer_output_size
参数可以修改发送长度限制 - 在发送超过8k的数据时, 底层会启用worker进程的共享内存, 需要进行一次
Mutex->lock
操作
- 如果数据大小超过2M, 应将文件写入临时文件, 然后通过
sendfile
未完待续