遵守规则可以让你远离选择烦恼,无论是在坐车还是参加鸡尾酒会的时候。 —《选择的悖论》

写在前面的话

此PhalApi扩展类库只是初步开发完成,建议有swoole扩展经验或非保守派的同学使用,也欢迎你来丰富完善此扩展类库。

3.9.1 扩展类库:swoole支持下的长链接和异步任务实现

swoole官网请见: Swoole: PHP的异步、并行、分布式扩展

在这里,首先需要非常感谢swoole。

因为Swoole给我们提供了很多解决以往因PHP本身限制而产生的难题的灵感,但与此同时,也给我们带来了从没遇到过的挑战,特别是并发和长时间运行。

这需要我们更为小心地进行编码,因为以往可以忽略的小问题,在新的解决方案背景下都可能成为一个大问题。此扩展类库更多是作为一种尝试,并且可以作为扩展类库重要的一个转换点。因为在今后的日子里, PhalApi将会争取与其他开源项目一起,提供企业级的解决方案

目前,此扩展类库提供了:

  • 长链接的接口调用
  • 异步计划任务的调用

    3.9.2 安装

(1)安装swoole扩展类库安装过程可以参考swoole官网,这里稍以linux系统简单说明一下编译安装。

  1. unzip ./swoole-src-swoole-1.7.16-beta.zip
  2. cd swoole-src-swoole-1.7.16-beta
  3. phpize
  4. ./configure
  5. make && make install

安装好后,添加swoole扩展:

  1. extension=swoole.so

重启PHP后,如果看到有swoole扩展,则说明安装成功:

  1. #php -m | grep swoole
  2. swoole

(2)扩展包下载

PhalApi-Library 扩展库中下载获取 Swoole 包,如使用:

  1. $ git clone https://git.oschina.net/dogstar/PhalApi-Library.git

然后把 Swoole 目录复制到 ./PhalApi/Library/ 下,即:

  1. $ cp ./PhalApi-Library/Swoole/ ./PhalApi/Library/ -R

到此安装完毕!

温馨提示:此扩展类库需要PhaApi 1.1.4及以上版本。

(3)配置

将以下配置追加到./Config/app.php:

  1. /**
  2. * Swoole扩展类库
  3. */
  4. 'Swoole' => array(
  5. //服务
  6. 'server' => array(
  7. 'ip' => '127.0.0.1',
  8. 'port' => 9501,
  9. 'worker_num' => 1,
  10. ),
  11. //计划任务
  12. 'task' => array(
  13. 'ip' => '127.0.0.1',
  14. 'port' => 9502,
  15. 'worker_num' => 1,
  16. ),
  17. ),

3.9.3 入门使用

(1)长链接入口

在使用长链接入口对外提供接口服务后,由于不再是HTTP协议,所以入口建议放置在新的目录./Server,而不再是./Public。入口文件的编写,如同我们以往一样,很简单:

  1. //$ vim ./Server/run_server.php
  2. <?php
  3. require_once dirname(__FILE__) . '/../Public/init.php';
  4. DI()->loader->addDirs(array('Library', 'Demo'));
  5. $swooleLite = new Swoole_Lite();
  6. $swooleLite->runServer();

启动、重启和关闭服务

启动可以用:

  1. php ./Server/run_server.php

关闭可以用:

  1. ps -ef | grep run_server | grep -v grep | awk '{print $2}'|xargs kill -9

(2)异步计划任务

异步计划任务是新型的做法,即:也通过接口服务调用的方式来完成计划任务的调度,其启动文件如同长链接入口一样简单:

  1. //$ vim ./Server/run_task.php
  2. <?php
  3. require_once dirname(__FILE__) . '/../Public/init.php';
  4. DI()->loader->addDirs(array('Library', 'Demo'));
  5. $swooleLite = new Swoole_Lite();
  6. $swooleLite->runTask();

启动、重启和关闭服务

启动可以用:

  1. nohup php ./Server/run_task.php > ./Server/run_task.log 2>&1 &

(3)客户端调用

在扩展类库里有一个测试的脚本,可以用来进行PHP客户端的请求。

(1)默认接口调用

  1. $ php ./check.php 127.0.0.1 9501 Default.Index username=swoole
  2. Send: {"service":"Default.Index","username":"swoole"}
  3. Received: {"ret":200,"data":{"title":"Hello World!","content":"Hi swoole, welcome to use PhalApi!","version":"1.1.3","time":1430620911},"msg":""}
  4. Connection close

(2)带数据库的调用

  1. $ php ./check.php 127.0.0.1 9501 User.getBaseInfo userId=1
  2. Send: {"service":"User.getBaseInfo","userId":"1"}
  3. 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":""}
  4. Connection close

(3)异步计划任务的调度

  1. $ php ./check.php 127.0.0.1 9502 Default.Index username=swoole
  2. Send: {"service":"Default.Index","username":"swoole"}
  3. Connection close

假设Default.Index为一个计划任务的接口,但目前发现一个问题是,首次请求异步计划任务不会主动结束,而需要工作强制ctrl + c结束,再请求,则正常。

对应的log,可以看到:

  1. 2015-05-03 12:24:57|DEBUG|asynctask(0) dispath in swoole|{"service":"Default.Index","username":"swoole"}
  2. 2015-05-03 12:24:57|DEBUG|asynctask(0) start in swoole|{"service":"Default.Index","username":"swoole"}
  3. 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":""}
  4. 2015-05-03 12:24:57|DEBUG|asynctask(1) dispath in swoole|{"service":"Default.Index","username":"swoole"}
  5. 2015-05-03 12:24:57|DEBUG|asynctask(1) start in swoole|{"service":"Default.Index","username":"swoole"}
  6. 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":""}
  7. ...

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文件的解析,所以在对项目代码(包括配置)修改后,需要重启服务,方能生效。


原文: https://www.phalapi.net/wikis/3-9.html