swoole支持下的长链接和异步任务实现
遵守规则可以让你远离选择烦恼,无论是在坐车还是参加鸡尾酒会的时候。 --《选择的悖论》
写在前面的话
此PhalApi扩展类库只是初步开发完成,建议有swoole扩展经验或非保守派的同学使用,也欢迎你来丰富完善此扩展类库。
3.9.1 扩展类库:swoole支持下的长链接和异步任务实现
swoole官网请见: Swoole: PHP的异步、并行、分布式扩展
在这里,首先需要非常感谢swoole。
因为Swoole给我们提供了很多解决以往因PHP本身限制而产生的难题的灵感,但与此同时,也给我们带来了从没遇到过的挑战,特别是并发和长时间运行。
这需要我们更为小心地进行编码,因为以往可以忽略的小问题,在新的解决方案背景下都可能成为一个大问题。此扩展类库更多是作为一种尝试,并且可以作为扩展类库重要的一个转换点。因为在今后的日子里, PhalApi将会争取与其他开源项目一起,提供企业级的解决方案 。
目前,此扩展类库提供了:
- 长链接的接口调用
- 异步计划任务的调用
3.9.2 安装
(1)安装swoole扩展类库 安装过程可以参考swoole官网,这里稍以linux系统简单说明一下编译安装。
unzip ./swoole-src-swoole-1.7.16-beta.zip
cd swoole-src-swoole-1.7.16-beta
phpize
./configure
make && make install
安装好后,添加swoole扩展:
extension=swoole.so
重启PHP后,如果看到有swoole扩展,则说明安装成功:
#php -m | grep swoole
swoole
(2)扩展包下载
从 PhalApi-Library 扩展库中下载获取 Swoole 包,如使用:
git clone https://git.oschina.net/dogstar/PhalApi-Library.git
然后把 Swoole 目录复制到 ./PhalApi/Library/ 下,即:
cp ./PhalApi-Library/Swoole/ ./PhalApi/Library/ -R
到此安装完毕!
温馨提示:
此扩展类库需要PhaApi 1.1.4及以上版本。
(3)配置
将以下配置追加到./Config/app.php:
/**
* Swoole扩展类库
*/
'Swoole' => array(
//服务
'server' => array(
'ip' => '127.0.0.1',
'port' => 9501,
'worker_num' => 1,
),
//计划任务
'task' => array(
'ip' => '127.0.0.1',
'port' => 9502,
'worker_num' => 1,
),
),
3.9.3 入门使用
(1)长链接入口
在使用长链接入口对外提供接口服务后,由于不再是HTTP协议,所以入口建议放置在新的目录./Server,而不再是./Public。
入口文件的编写,如同我们以往一样,很简单:
//$ vim ./Server/run_server.php
<?php
require_once dirname(__FILE__) . '/../Public/init.php';
DI()->loader->addDirs(array('Library', 'Demo'));
$swooleLite = new Swoole_Lite();
$swooleLite->runServer();
启动、重启和关闭服务
启动可以用:
php ./Server/run_server.php
关闭可以用:
ps -ef | grep run_server | grep -v grep | awk '{print $2}'|xargs kill -9
(2)异步计划任务
异步计划任务是新型的做法,即:也通过接口服务调用的方式来完成计划任务的调度,其启动文件如同长链接入口一样简单:
//$ vim ./Server/run_task.php
<?php
require_once dirname(__FILE__) . '/../Public/init.php';
DI()->loader->addDirs(array('Library', 'Demo'));
$swooleLite = new Swoole_Lite();
$swooleLite->runTask();
启动、重启和关闭服务
启动可以用:
nohup php ./Server/run_task.php > ./Server/run_task.log 2>&1 &
(3)客户端调用
在扩展类库里有一个测试的脚本,可以用来进行PHP客户端的请求。
(1)默认接口调用
$ php ./check.php 127.0.0.1 9501 Default.Index username=swoole
Send: {"service":"Default.Index","username":"swoole"}
Received: {"ret":200,"data":{"title":"Hello World!","content":"Hi swoole, welcome to use PhalApi!","version":"1.1.3","time":1430620911},"msg":""}
Connection close
(2)带数据库的调用
$ php ./check.php 127.0.0.1 9501 User.getBaseInfo userId=1
Send: {"service":"User.getBaseInfo","userId":"1"}
Received: {"ret":200,"data":{"code":0,"msg":"","info":{"id":"1","username":"aevit","nickname":"test","password":"DE4CA99150F44B26F0D320DCA6E4B7629C43B6","salt":"wefewfew","reg_time":"0","avatar":"http:\/\/image.famillelab.com\/no_avatar.png","UUID":""}},"msg":""}
Connection close
(3)异步计划任务的调度
$ php ./check.php 127.0.0.1 9502 Default.Index username=swoole
Send: {"service":"Default.Index","username":"swoole"}
Connection close
假设Default.Index为一个计划任务的接口,但目前发现一个问题是,首次请求异步计划任务不会主动结束,而需要工作强制ctrl + c结束,再请求,则正常。
对应的log,可以看到:
2015-05-03 12:24:57|DEBUG|asynctask(0) dispath in swoole|{"service":"Default.Index","username":"swoole"}
2015-05-03 12:24:57|DEBUG|asynctask(0) start in swoole|{"service":"Default.Index","username":"swoole"}
2015-05-03 12:24:57|DEBUG|asynctask(0) finish in swoole|{"ret":200,"data":{"title":"Hello World!","content":"Hi swoole, welcome to use PhalApi!","version":"1.1.3","time":1430627097},"msg":""}
2015-05-03 12:24:57|DEBUG|asynctask(1) dispath in swoole|{"service":"Default.Index","username":"swoole"}
2015-05-03 12:24:57|DEBUG|asynctask(1) start in swoole|{"service":"Default.Index","username":"swoole"}
2015-05-03 12:24:57|DEBUG|asynctask(1) finish in swoole|{"ret":200,"data":{"title":"Hello World!","content":"Hi swoole, welcome to use PhalApi!","version":"1.1.3","time":1430627097},"msg":""}
...
3.9.4 对客户端调整
(1)调用方式的改变
改用长链接。
(2)POST参数传递方式的改变
统一使用json发送数据包。
3.9.5 对服务端的影响
(1)DI资源服务的调整
变量名称 | 是否全局通用 | 是否每次请求新建 | 可否使用 | 备注 |
---|---|---|---|---|
loader | 是 | 否 | 可使用 | |
config | 是 | 否 | 可使用 | |
logger | 是 | 否 | 可使用 | |
notorm | 是 | 否 | 可使用 | 每次响应后,关闭此次全部数据库链接 |
cache | 是 | 否 | 可使用 | 需要查看使用的链接是否支持长链接 |
filter | 是 | 否 | 可使用 | |
crypt | 是 | 否 | 可使用 | |
curl | 是 | 否 | 可使用 | |
request | 否 | 是 | 可使用 | |
response | 否 | 是 | 可使用 | |
cookie | --- | --- | 不可使用 | 长链接下不应进行COOKIE的操作 |
(2)关于swoole扩展类库的自问自答
- 1、数据库使用长链接吗? -- 不使用,每次响应后手动关闭数据链接
- 2、内存问题?-- 通过类成员方法的作用域控制内存
- 3、并发的问题?-- TODO
- 4、代码更新后如何同步?需要重启服务器吗? -- 需要重启
- 5、PhalApi_Response::formatResult()的访问权限,是框架的调整,还是个别自我提高? -- 扩展自我提高
- 6、注册错误回调函数? -- 来自swoole的建议,已注册
- 7、启动和关闭、重启脚本文件? -- 提供参考命令
- 8、一直运行? -- TODO
(3)特别注意!
由于服务在启动后,已经完成了大部分的类加载、配置读取以及PHP文件的解析,所以在对项目代码(包括配置)修改后,需要重启服务,方能生效。