💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
##2.22.1 PHPUnit:自动化单元测试 目前核心框架单元测试的覆盖率(高达90%以上!!!此处应该有掌声~): ![a pic](http://webtools.qiniudn.com/131634_NHlk_256338.jpg) 注意,此测试截图并不是最新的,但我们一直都在致力坚持单元测试。 这一点,你可以在单元测试的代码中找到证明。 ##2.22.2 Phing:一键部署、快速发布 无论如何,都应该走自动化发布流程,避免人工地打包、上传、解压、改生产配置这些重复性的人工操作。 在自动化发布中,Phing是个不错的尝试。 以下是我某个项目中的使用配置,出于对项目的保护,部分数据已删除,但仍然可以参考。 ###(1)发布配置 - build.xml 主要的操作有: + 1. 备份当前代码,并删除一天前的备份 + 2. 从SVN签出最新的发布代码 + 3. 执行配置检测脚本 + 4. 代码发布切换,并替换使用线上配置文件 + 5. 移除单元测试初始化文件,以免误执行 ```javascript <?xml version="1.0" encoding="UTF-8"?> <!-- ============================================ --> <!-- PhalApi --> <!-- @dogstar 20141221 --> <!-- ============================================ --> <project name="demo.phalapi.com" default="build"> <property name="backup_path" value="/home/apps/backup/demo.phalapi.com" override="true" /> <property name="backup_prefix" value="demo.phalapi.com_phing_backup_" override="true" /> <property name="svn_todir" value="/home/apps/svn/demo.phalapi.com" override="true" /> <!-- ============================================ --> <!-- Target: prepare --> <!-- ============================================ --> <target name="prepare"> <mkdir dir="./Runtime" /> <mkdir dir="${svn_todir}" /> <mkdir dir="${backup_path}" /> </target> <!-- ============================================ --> <!-- Target: svn checkout --> <!-- ============================================ --> <target name="svncheckout"> <svncheckout repositoryurl="svn://127.0.0.1/PhalApi/demo/release" username="test" password="123456" nocache="true" todir="${svn_todir}" /> </target> <!-- ============================================ --> <!-- Target: svn update --> <!-- ============================================ --> <target name="svnup" depends="svncheckout"> <svnupdate repositoryurl="svn://127.0.0.1/PhalApi/demo/release" username="test" password="123456" nocache="true" todir="${svn_todir}" /> </target> <!-- ============================================ --> <!-- Target: check config --> <!-- ============================================ --> <target name="checkconfig"> <php expression="include('${svn_todir}/Tools/check_config.php')" /> <php function="checkProd" class="Tools_Check_Config" returnProperty="checkProdErrorMsg" /> <fail msg="${checkProdErrorMsg}" if="checkProdErrorMsg" /> </target> <!-- ============================================ --> <!-- Target: backup --> <!-- ============================================ --> <target name="backup"> <php expression="date('Ymd', strtotime('-1 day'))" returnProperty="backup_version_yesterday" /> <php expression="date('Ymd')" returnProperty="backup_version_today" /> <delete> <fileset dir="${backup_path}"> <exclude name="${backup_prefix}${backup_version_yesterday}*" /> <exclude name="${backup_prefix}${backup_version_today}*" /> </fileset> </delete> <php expression="date('YmdHis')" returnProperty="backup_version" /> <zip destfile="${backup_path}/${backup_prefix}${backup_version}.zip" basedir="." > <fileset dir="."> <include name="**/**" /> <exclude name="./Runtime" /> <exclude name="./Runtime/**" /> <exclude name="./.svn" /> <exclude name="./.svn/**" /> </fileset> </zip> <copy file="${backup_path}/${backup_prefix}${backup_version}.zip" tofile="${backup_path}/${backup_prefix}lastest.zip" overwrite="true" /> </target> <!-- ============================================ --> <!-- Target: build --> <!-- ============================================ --> <target name="build" depends="prepare,svnup,checkconfig,backup"> <copy todir="." overwrite="true" > <fileset dir="${svn_todir}"> <include name="**/**" /> <exclude name="${svn_todir}/Config/dbs.php" /> <exclude name="${svn_todir}/Config/sys.php" /> <exclude name="${svn_todir}/Test" /> <exclude name="${svn_todir}/Test/**" /> </fileset> </copy> <copy file="./Config/dbs.php.prod" tofile="./Config/dbs.php" overwrite="true" /> <copy file="./Config/sys.php.prod" tofile="./Config/sys.php" overwrite="true" /> <!-- 避免在生产环境执行PHPUnit,故把测试环境的初始文件移开 --> <move file="./Test/test_env.php" tofile="./Test/test_env.php.bak" overwrite="true"/> </target> </project> ``` ###(2)回滚配置 - rollback.xml 主要操作: + 1. 回滚到上一个版本 ```javascript <?xml version="1.0" encoding="UTF-8"?> <!-- ============================================ --> <!-- PhalApi --> <!-- @dogstar 20141222 冬至 --> <!-- ============================================ --> <project name="demo.phalapi.com" default="rollback"> <property name="backup_path" value="/home/apps/backup/demo.phalapi.com" override="true" /> <property name="backup_prefix" value="demo.phalapi.com_phing_backup_" override="true" /> <property name="svn_todir" value="./__svn__" override="true" /> <!-- ============================================ --> <!-- Target: rollback --> <!-- ============================================ --> <target name="rollback" > <unzip file="${backup_path}/${backup_prefix}lastest.zip" todir="." > <fileset dir="."> <include name="*.zip"/> </fileset> </unzip> </target> </project> ``` ##2.22.3 autobench:接口压力测试与可视化图表 可以通过以下的脚本来进行,使用示例: ```javascript $ ./autobench.sh Usage: ./autobench.sh <host> <uri> - ./autobench.sh www.baidu.com /index.php ``` 参数可以自行调整。 ###(1)利用bench2graph生成可视化图表 ####纯PHP访问 - 入口欢迎接口 ![a pic](http://webtools.qiniudn.com/1421422942BjP7K5M5.jpg) ####mysql访问 - 事件获取接口 ![a pic](http://webtools.qiniudn.com/14214229738ftM0Nck.jpg) ####带MC缓存的访问 - 应用入口 - 带缓存的身份token验证 ![a pic](http://webtools.qiniudn.com/1421424027OYV4Ae5i.jpg) ###(2)详细的数据报表 ```javascript dem_req_rate req_rate_demo.phalapi.com con_rate_demo.phalapi.com min_rep_rate_demo.phalapi.com avg_rep_rate_demo.phalapi.com max_rep_rate_demo.phalapi.com stddev_rep_rate_demo.phalapi.com resp_time_demo.phalapi.com net_io_demo.phalapi.com errors_demo.phalapi.com 5 5.0 5.0 4.8 5.0 5.2 0.1 22.4 2.9 0 25 25.0 25.0 25.0 25.0 25.0 0.0 21.6 14.3 0 45 45.0 45.0 45.0 45.0 45.0 0.0 22.3 25.7 0 65 64.9 64.9 64.7 64.7 64.7 0.0 25.4 37.0 0 85 84.8 84.8 84.6 84.6 84.6 0.0 28.6 48.3 0 105 104.6 104.6 0.0 0.0 0.0 0.0 34.4 59.7 0 125 124.0 124.0 0.0 0.0 0.0 0.0 42.2 70.7 0 145 143.8 143.8 0.0 0.0 0.0 0.0 59.2 82.0 0 165 147.4 147.4 0.0 0.0 0.0 0.0 262.9 84.1 0 185 151.1 151.1 0.0 0.0 0.0 0.0 429.7 86.2 0 ``` ###(3)附脚本 ```javascript #!/bin/bash if [ $# -eq 0 ]; then echo "Usage: $0 <host> <uri>" echo "" echo " - $0 www.baidu.com /index.php" echo "" exit fi DM=$1 URL=$2 #--signle_host 只测单机 #--host1 测试主机地址 #--uri1 host1 测试URI #--quiet 安静模式 #--low_rate 测试时最低请求数(指 httperf) #--hight_rate 测试时最高请求数 #--rate_step 每次测试请求数增加步长 #--num-call 每连接中发起联接数,一般是1 #--num_conn 测试联接数 #--file 测试结果输出的 tsv文件 autobench \ --single_host \ --host1=$DM \ --port1=80 \ --uri1=$URL \ --low_rate=5 \ --high_rate=200 \ --rate_step=20 \ --num_call=1 \ --num_conn=500 \ --timeout=10 \ --file ./$DM.tsv ``` ##2.22.4 xhprof:性能分析工具 xhprof是一个不错的内部性能分析工具,这里不过多的讲述此工具的特点和使用,但会以对PhalApi进行的一个性能测试展示它的分析效果。 ###(1)测试的接口服务 http://api.phalapi.com /demo/?service=Default.Index&username=test ###(2)Overall Summary ```javascript Total Incl. Wall Time (microsec): 7,873 microsecs Total Incl. CPU (microsecs): 7,999 microsecs Total Incl. MemUse (bytes): 304,456 bytes Total Incl. PeakMemUse (bytes): 306,616 bytes Number of Function Calls: 338 ``` ###(3)Top 10耗时 Function Name|Calls|Calls%|Incl. Wall Time(microsec)|IWall%(microsec)|Excl. Wall Time|EWall% ---|---|---|---|---|---|--- PhalApi_Loader::loadClass| 10| 3.00%| 3,020| 38.40%| 1,038| 13.20% PhalApi_Loader::loadClass1| 4| 1.20%| 785| 10.00%| 398| 5.10% run_init::Public/init.php| 1| 0.30%| 3,915| 49.70%| 327| 4.20% file_exists| 18| 5.30%| 249| 3.20%| 249| 3.20% main()| 1| 0.30%| 7,873| 100.00%| 248| 3.20% load::zh_cn/common.php| 2| 0.60%| 237| 3.00%| 237| 3.00% PhalApi_Loader::load| 9| 2.70%| 3,380| 42.90%| 226| 2.90% PhalApi_DI::get| 9| 2.70%| 1,268| 16.10%| 223| 2.80% PhalApi_Translator::addMessage| 2| 0.60%| 522| 6.60%| 136| 1.70% DI| 15| 4.40%| 645| 8.20%| 134| 1.70% class_exists| 11| 3.30%| 1,383| 17.60%| 130| 1.70% load::Config/sys.php| 1| 0.30%| 120| 1.50%| 120| 1.50% 对应的图表如下: ![a pic](http://webtools.qiniudn.com/phalapi_xhprxf.jpg) 从中可以看出,主要的耗时途径在于文件的加载,下面将进一步探讨。 ###(4)Top 1耗时深入 ![a pic](http://webtools.qiniudn.com/top1_sheet-small.png) 所加载的文件如下: ![a pic](http://webtools.qiniudn.com/top1_loader.png) ##2.22.5 Jenkis和Sonar:持续集成和静态代码分析 PhalApi从来不会隐藏自己的设计,当然,我们也不会隐藏我们内部的各个细节以及存在的问题。 但和其他隐藏了技术债务的框架相比,PhalApi敢于展示自己的静态代码分析报告,并且它也是做得相当出色的。 以下截图来自 GIT@OSC 上的静态代码分析: ![a pic](http://webtools.qiniudn.com/sonar_code_analysis.png) 当你的项目很重要时,也可以使用Jenkis或者Sonar进行静态代码的分析。 不要个人主观地觉得你的代码风格写得好,而是交由专业的分析工具进行解剖,并理解各个数据报表背后的含义,然后改进之。 ##2.22.6 Git/SVN:更多的版本控制 ##2.22.7 WIKI:团队沟通与文档交流 ###(1)markdown接口模板 ``` #3.2 接口文档模板 ##1、功能说明 _请在这里放置简短的接口功能说明。_ ##2、接口URL /?service= _接口服务名称_ + 公共参数(是否免登录态?) ##3、接口参数 [跳转](http://demo.phalapi.com/demo/checkApiParams.php?service=) 参数|必须|默认值|说明 ---|---|---|--- user_id|1||用户id ##4、返回结果 ###返回字段 参数|类型|说明 ---|---|--- data.username|string|用户名 ###结果示例 { "ret": 200, "data": { .... //更多结果的说明 "msg": "" }, "msg": "" } ###请求示例 _请放置一个接口请求的链接。_ http://demo.phalapi.com/demo/?service= ``` ##2.22.8 静态代码分析工具 - phpmetrics 以下是针对本框架核心代码所做的分析报告: ![a pic](http://7qnay5.com1.z0.glb.clouddn.com/QQ截图20150807230905.jpg) ![a pic](http://7qnay5.com1.z0.glb.clouddn.com/QQ截图20150807230920.jpg) PS:从报告的评估可以看出,我们的框架明显具有相当 高的可维护性。