-
Notifications
You must be signed in to change notification settings - Fork 18
helpManual swoole
//强制使用网络方式, 保证网络"异步请求回调"也在Swoole中 _of.com.net.isCli = false; //异步请求网络, 注意端口正确 _of.com.net.async = 'http://127.0.0.1:8888/'; //swoole异步任务方式 _of.com.timer.fork.adapter = 'swoole';
<?php
//以下为默认配置
return array(
//系统配置
'system' => array(
//开启服务, 默认支持http的WebSocket协议服务, 绝对路径则为自定义服务(如: /var/www/html/test.php 参考下方demo)
'open' => 'WebSocket',
//监听端口, 默认8888
'port' => 8888,
//工作进程超过该时间会安全重启, 单位秒, 默认0不限制
'cycle' => 0,
//工作进程超过该内存会安全重启, 支持K M G单位(如: 1G), 默认0不限制
'memory' => 0,
//启动配置的绝对路径, 仅在启动参数conf为json格式中生效, json中配置优先级高于路径中配置, 如"conf:{'system':{'config':'/var/www/xxx.php'}}"
'config' => '',
//健康检查网址, 可用于初始化, 约10s一次(如: http://127.0.0.1:8888/include/of/index.php), 默认""
'health' => '',
//路由规则, 格式不含GET的路径后再与GET合并, 参考preg_replace前两参数, 如: {"@^(/[^/]+)/.*$@" : "$1.php?a=1", ...}
'routes' => array(),
//自定义初始化列表, 会在每个协程加载框架完成时执行, [框架回调结构, ...]
'reinit' => array(),
//自定义常量
'define' => array(
//系统根路径, 默认为swoole.php所在的目录
'ROOT_DIR' => __DIR__,
//框架根路径
'OF_DIR' => __DIR__ . '/include/of',
)
),
//服务配置
'server' => array(
//启动协程化(无法修改)
'enable_coroutine' => true,
//安全重启最大等待时间(s), 超时强杀
'max_wait_time' => 86400,
//协程函数范围, 默认全覆盖, 选项参考
'hook_flags' => SWOOLE_HOOK_ALL | SWOOLE_HOOK_CURL,
//服务启动进程数, 默认CPU核数, 框架限制每个进程同时处理1000个请求
'worker_num' => swoole_cpu_num(),
//错误日志记录等级
'log_level' => SWOOLE_LOG_WARNING,
//协程抢占式调度, 默认false关闭, 若为true对密集运算的协程更友好(需更多CPU资源)
'enable_preemptive_scheduler' => false,
//最大数据包
'package_max_length' => ini_get('post_max_size')的字节数,
//更多参考TCP/UDP与HTTP配置
...
),
//替代PHP配置, 如max_execution_time在cli模式下永远是0, 因此设置到这里
'phpIni' => array(
//请求响应超时时间, 默认30s, 等同set_time_limit(30), 此值为包含网络等操作的实际执行时间
'max_execution_time' => 30,
//协程静态变量最大内存空间
'memory_limit' => ini_get('memory_limit'),
//日期时间函数使用的默认时区
'date.timezone' => date_default_timezone_get()
)
);
单个请求的效率提升基本无感知, 甚至可能因为过多协程的调度导致执行速度更慢 每个Swoole进程可同时响应多个请求(框架限制为1000), Ngnix与其相比需要启动更多php进程 Swoole支持的通信协议与并发任务是切实改变开发思维的壮举, 当然这些也需要资源的加持
php官网说明如下 set_time_limit()函数和配置指令max_execution_time只影响脚本本身执行的时间。 任何发生在诸如使用system()的系统调用,流操作,数据库操作等脚本的执行时间不包括其中。 在Windows上为实际执行时间。Swoole与Windows行为一致, 默认情况下是无需设置的 1. 计划任务永不超时 2. 消息队列每条是2小时超时, 超过分秒级应该改造队列 3. 网络请求若调整执行时间, 应设置在ctrl层或入口文件
可以通过两种方式优化 1. 调整启动配置 phpIni.max_execution_time 的默认值 2. 通过 set_time_limit(int) 或 ini_set('max_execution_time', int) 动态设置
<?php
//全局的, 无参数 => 正常运行
class::init();
//全局的, 无参数 => 正常运行
class::_init();
//非全局(在方法或类中), 有参数 => 正常运行
function () {class::init(1);}
//全局的, 有参数 => 运行报错
class::init(1);
//全局的, 无参数 => 正常运行, 但不正确, 每次请求都不会判断而执行init, 应把条件放在init中
if (true) {class::init();}
//同时也意味着其它初始化作用的方法名无效 => 无法每次运行, 这类情况可配置reinit参数
class::abcd();
<?php
//安装SIGTERM信号处理器
pcntl_signal(15, function ($signo) {}) :
//恢复linux进程对SIGTERM信号处理
pcntl_signal(15, SIG_DFL);
//检查信号
pcntl_signal_dispatch();
-
namestring数据名称
-
dataarray初始数据, 默认空数组
<?php
//引用返回, 多协程初始化数据
$data = &swoole::data('test', array('init' => 0));
//多协程初始化动作(无锁方式实现)
++$data['init'] === 1 ? 初始化动作 : $data['init'] = 1;
-
callcallback符合框架回调结构, 包含协程逻辑, 可以是匿名函数
-
modeint
协程模式 1=工作协程, 启动快, 可共享变量, 过多影响调度速度, 适合跨协程操作的任务 2=独立进程, 启动慢, 支持更多"工作协程", 适合运行长时间的任务 4=共享进程, 启动快, 支持少量"工作协程", 适合运行短时间的任务
-
dataarray
mode为1时生效 { "space" :&当协程运行时被设置为协程ID, 引用传值, 默认无引用 "requ" : 指定请求信息, 符合Swoole\Http\Request属性的对象, 默认父协程的请求信息 "argv" : 指定call的触发参数, 参考of::callFunc, 默认无参数 }
<?php /** 运行的协程在收到SIGTERM信号后 1. 定时器会立刻退出 2. SIG_DFL默认处理方式的go协程会等到sleep时退出 3. 其它处理方式会在调用pcntl_signal_dispatch时安全退出 */ swoole::fork(array( //符合框架的回调结构 'asCall' => $call, 'params' => array($data) ));//模拟一个含两个必要属性的requ对象, 还可以添加get post等参数 $requ = new stdClass; $requ->server = array( 'path_info' => '/index.php', 'remote_addr' => $serv->getClientInfo($fd)['remote_ip'] ); //指定请求信息回调演示 swoole::fork($call, 1, array( 'requ' => $requ ));
1. 兼容原开发方式, 部署同Apache和Ngnix相同, 启动Swoole后便可应用 2. 建议Swoole仅作为应用服务器, 用Ngnix做代理, 转发动态的php请求
1. WebSocket连接时先加载入口文件, 需返回至少包含"info"的回调数组, {"init" : 初始回调, "info" : 信息回调, "done" : 结束回调}
2. 回调符合框架回调结构, 每个回调触发时接受一个数组参数, 结构如下
init({"link" : 连接ID, "resp" : 响应对象})
info({"link" : 连接ID, "resp" : 响应对象, "info" : 信息对象})
done({"link" : 连接ID})
3. 响应对象包含两个方法
push(string | array | 信息对象 $data) 推送信息, 数组参数转会为json, 成功返回true, 失败返回false
close() 发送关闭帧并关闭连接, 成功返回true, 失败返回false
4. 支持文本ping pong帧处理, 受open_websocket_ping_frame或open_websocket_pong_frame参数影响, 自动响应数据
{"ping" : "pong", "Ping" : "Pong", "PING" : "PONG"}
<?php
/**
info是必须的, 否则会直接关闭连接, init和done是可选的
假设文件路径 /test.php, 先进行登录验证等操作
*/
return array(
//连接成功回调
'init' => function ($params) {
$params['resp']->push(print_r($params, true));
},
//接受信息回调
'info' => function ($params) {
//发送信息
$params['resp']->push(print_r($params, true));
//关闭连接
$params['resp']->close();
}
);
?>
<script>
//创建连接, 注意端口
var websocket = new WebSocket('ws://127.0.0.1:8888/test.php');
//连接成功回调
websocket.onopen = function (evt) {
console.log("Connected to WebSocket server.");
//连接成功后发送信息
websocket.send('hello');
};
//接受信息回调
websocket.onmessage = function (evt) {
console.log('Retrieved data from server: ' + evt.data);
};
//关闭连接回调
websocket.onclose = function (evt) {
console.log("Disconnected");
};
//出现错误回调
websocket.onerror = function (evt, e) {
console.log('Error occured: ' + evt.data);
};
</script>
1. 自定义服务完整的Swoole服务代码写在独立的文件中并返回服务对象, 如: /var/www/html/demo.php 2. 服务代码中调用$GLOBALS中的"system server phpIni"分别对应配置文件中的数据, 键名可扩展 3. 可以调用swoole类的私有方法和属性, 如: self::request($requ, null); 4. 参考swoole.php中"webSocket"方法的代码能更容易实现大部分自定义服务的逻辑 5. 通过命令行启动自定义服务, 如: php swoole.php "open:/var/www/html/demo.php"
<?php
/**
演示http服务
假设文件路径 /var/www/html/demo.php
*/
$serv = new Swoole\Http\Server('0.0.0.0', $GLOBALS['system']['port'], SWOOLE_PROCESS);
//请求回调
$serv->on('request', function ($requ, $resp) {
//调用私有方法, 处理请求信息
self::request($requ, $resp);
});
//返回服务
return $serv;
##############################################################################################################
########服务开发的具体实现思路总体分五步, 客户端连接执行前三步, 接到消息执行第四步, 关闭连接执行第五步########
##############################################################################################################
//第一步拼接一个requ请求对象, 如:
$requ = new stdClass;
$requ->server = array(
//入口文件
'path_info' => '/index.php',
//客户端IP
'remote_addr' => $serv->getClientInfo($fd)['remote_ip']
);
//第二步调用swoole::request加载入口文件并保存入口文件返回的回调函数, 如:
$call = self::request($requ, null);
//第三步封装一个响应对象, 为应用层提供交互功能, 并把上述数据保存到静态变量中, 如:
$resp = new stdClass;
//第四步在接到客户端消息时, 通过指定请求信息和触发参数的方式创建协程回调, 如:
self::fork($call, 1, array(
//指定请求头
'requ' => $requ,
//触发参数, 内容自定义, 如: {"link" : 连接标识, "resp" : 响应对象, "info" : 客户消息}
'argv' => array('link' => $frame->fd, 'resp' => $resp, 'info' => $frame)
));
//第五步在关闭连接时清理连接标识对应的数据, 如:
unset($requ, $call, $resp);
手册地址 http://phpof.net/
- 入门指引
-
疑难解答
- 部署时会遇到的那些常见问题
简单却容易忽视 - 框架内置有哪些管理界面
生产模式进入界面需用 __OF_DEBUG__ - 如何定制不同的架构模式
通过配置入口文件中调度方法的参数即可 - 如何面向命名空间开发
of_xx 类可以按照命名空间方式调用 - 如何设置不同的部署模式
通过_of.debug设置 开发,测试,生产 模式 - 为什么控制层类文件要返回true
这是防止非法访问的方法之一 - 为什么传到视图层的变量会被编码
这是因为 XSS 安全防范的原因 - 为什么框架没有SQL构造器
因常规方案牺牲了性能又未很好解决问题 - 如何快速开发用户及权限管理功能
单点登录(SSO)模块因此而存在 - 怎么在系统的基础上扩展底层功能
三点: 扩展开发, 预先加载, 底层钩子 - 怎么使用 Composer 依赖管理工具
框架已集成, 默认关闭状态
- 部署时会遇到的那些常见问题
- 组件使用
- 集成插件
- 扩展开发
- 开发手册