2.22.1 PHPUnit:自动化单元测试

目前核心框架单元测试的覆盖率(高达90%以上!!!此处应该有掌声~):a pic

注意,此测试截图并不是最新的,但我们一直都在致力坚持单元测试。这一点,你可以在单元测试的代码中找到证明。

2.22.2 Phing:一键部署、快速发布

无论如何,都应该走自动化发布流程,避免人工地打包、上传、解压、改生产配置这些重复性的人工操作。

在自动化发布中,Phing是个不错的尝试。

以下是我某个项目中的使用配置,出于对项目的保护,部分数据已删除,但仍然可以参考。

(1)发布配置 - build.xml

主要的操作有:

    • 备份当前代码,并删除一天前的备份
    • 从SVN签出最新的发布代码
    • 执行配置检测脚本
    • 代码发布切换,并替换使用线上配置文件
    • 移除单元测试初始化文件,以免误执行
      1. <?xml version="1.0" encoding="UTF-8"?>

<!— ============================================ —>
<!— PhalApi —>
<!— @dogstar 20141221 —>
<!— ============================================ —>

<project name="demo.phalapi.com" default="build">

  1. &lt;property
  2. name=&#34;backup_path&#34;
  3. value=&#34;/home/apps/backup/demo.phalapi.com&#34;
  4. override=&#34;true&#34; /&gt;
  5. &lt;property
  6. name=&#34;backup_prefix&#34;
  7. value=&#34;demo.phalapi.com_phing_backup_&#34;
  8. override=&#34;true&#34; /&gt;
  9. &lt;property
  10. name=&#34;svn_todir&#34;
  11. value=&#34;/home/apps/svn/demo.phalapi.com&#34;
  12. override=&#34;true&#34; /&gt;
  13. &lt;!-- ============================================ --&gt;
  14. &lt;!-- Target: prepare --&gt;
  15. &lt;!-- ============================================ --&gt;
  16. &lt;target name=&#34;prepare&#34;&gt;
  17. &lt;mkdir dir=&#34;./Runtime&#34; /&gt;
  18. &lt;mkdir dir=&#34;${svn_todir}&#34; /&gt;
  19. &lt;mkdir dir=&#34;${backup_path}&#34; /&gt;
  20. &lt;/target&gt;
  21. &lt;!-- ============================================ --&gt;
  22. &lt;!-- Target: svn checkout --&gt;
  23. &lt;!-- ============================================ --&gt;
  24. &lt;target name=&#34;svncheckout&#34;&gt;
  25. &lt;svncheckout
  26. repositoryurl=&#34;svn://127.0.0.1/PhalApi/demo/release&#34;
  27. username=&#34;test&#34;
  28. password=&#34;123456&#34;
  29. nocache=&#34;true&#34;
  30. todir=&#34;${svn_todir}&#34; /&gt;
  31. &lt;/target&gt;
  32. &lt;!-- ============================================ --&gt;
  33. &lt;!-- Target: svn update --&gt;
  34. &lt;!-- ============================================ --&gt;
  35. &lt;target name=&#34;svnup&#34; depends=&#34;svncheckout&#34;&gt;
  36. &lt;svnupdate
  37. repositoryurl=&#34;svn://127.0.0.1/PhalApi/demo/release&#34;
  38. username=&#34;test&#34;
  39. password=&#34;123456&#34;
  40. nocache=&#34;true&#34;
  41. todir=&#34;${svn_todir}&#34; /&gt;
  42. &lt;/target&gt;
  43. &lt;!-- ============================================ --&gt;
  44. &lt;!-- Target: check config --&gt;
  45. &lt;!-- ============================================ --&gt;
  46. &lt;target name=&#34;checkconfig&#34;&gt;
  47. &lt;php expression=&#34;include(&#39;${svn_todir}/Tools/check_config.php&#39;)&#34; /&gt;
  48. &lt;php
  49. function=&#34;checkProd&#34;
  50. class=&#34;Tools_Check_Config&#34;
  51. returnProperty=&#34;checkProdErrorMsg&#34; /&gt;
  52. &lt;fail msg=&#34;${checkProdErrorMsg}&#34; if=&#34;checkProdErrorMsg&#34; /&gt;
  53. &lt;/target&gt;
  54. &lt;!-- ============================================ --&gt;
  55. &lt;!-- Target: backup --&gt;
  56. &lt;!-- ============================================ --&gt;
  57. &lt;target name=&#34;backup&#34;&gt;
  58. &lt;php
  59. expression=&#34;date(&#39;Ymd&#39;, strtotime(&#39;-1 day&#39;))&#34;
  60. returnProperty=&#34;backup_version_yesterday&#34; /&gt;
  61. &lt;php
  62. expression=&#34;date(&#39;Ymd&#39;)&#34;
  63. returnProperty=&#34;backup_version_today&#34; /&gt;
  64. &lt;delete&gt;
  65. &lt;fileset dir=&#34;${backup_path}&#34;&gt;
  66. &lt;exclude name=&#34;${backup_prefix}${backup_version_yesterday}*&#34; /&gt;
  67. &lt;exclude name=&#34;${backup_prefix}${backup_version_today}*&#34; /&gt;
  68. &lt;/fileset&gt;
  69. &lt;/delete&gt;
  70. &lt;php
  71. expression=&#34;date(&#39;YmdHis&#39;)&#34;
  72. returnProperty=&#34;backup_version&#34; /&gt;
  73. &lt;zip destfile=&#34;${backup_path}/${backup_prefix}${backup_version}.zip&#34; basedir=&#34;.&#34; &gt;
  74. &lt;fileset dir=&#34;.&#34;&gt;
  75. &lt;include name=&#34;**/**&#34; /&gt;
  76. &lt;exclude name=&#34;./Runtime&#34; /&gt;
  77. &lt;exclude name=&#34;./Runtime/**&#34; /&gt;
  78. &lt;exclude name=&#34;./.svn&#34; /&gt;
  79. &lt;exclude name=&#34;./.svn/**&#34; /&gt;
  80. &lt;/fileset&gt;
  81. &lt;/zip&gt;
  82. &lt;copy
  83. file=&#34;${backup_path}/${backup_prefix}${backup_version}.zip&#34;
  84. tofile=&#34;${backup_path}/${backup_prefix}lastest.zip&#34;
  85. overwrite=&#34;true&#34; /&gt;
  86. &lt;/target&gt;
  87. &lt;!-- ============================================ --&gt;
  88. &lt;!-- Target: build --&gt;
  89. &lt;!-- ============================================ --&gt;
  90. &lt;target name=&#34;build&#34; depends=&#34;prepare,svnup,checkconfig,backup&#34;&gt;
  91. &lt;copy todir=&#34;.&#34; overwrite=&#34;true&#34; &gt;
  92. &lt;fileset dir=&#34;${svn_todir}&#34;&gt;
  93. &lt;include name=&#34;**/**&#34; /&gt;
  94. &lt;exclude name=&#34;${svn_todir}/Config/dbs.php&#34; /&gt;
  95. &lt;exclude name=&#34;${svn_todir}/Config/sys.php&#34; /&gt;
  96. &lt;exclude name=&#34;${svn_todir}/Test&#34; /&gt;
  97. &lt;exclude name=&#34;${svn_todir}/Test/**&#34; /&gt;
  98. &lt;/fileset&gt;
  99. &lt;/copy&gt;
  100. &lt;copy
  101. file=&#34;./Config/dbs.php.prod&#34;
  102. tofile=&#34;./Config/dbs.php&#34;
  103. overwrite=&#34;true&#34; /&gt;
  104. &lt;copy
  105. file=&#34;./Config/sys.php.prod&#34;
  106. tofile=&#34;./Config/sys.php&#34;
  107. overwrite=&#34;true&#34; /&gt;
  108. &lt;!-- 避免在生产环境执行PHPUnit,故把测试环境的初始文件移开 --&gt;
  109. &lt;move
  110. file=&#34;./Test/test_env.php&#34;
  111. tofile=&#34;./Test/test_env.php.bak&#34;
  112. overwrite=&#34;true&#34;/&gt;
  113. &lt;/target&gt;

</project>

(2)回滚配置 - rollback.xml

主要操作:

    • 回滚到上一个版本
      1. <?xml version="1.0" encoding="UTF-8"?>

<!— ============================================ —>
<!— PhalApi —>
<!— @dogstar 20141222 冬至 —>
<!— ============================================ —>

<project name="demo.phalapi.com" default="rollback">

  1. &lt;property
  2. name=&#34;backup_path&#34;
  3. value=&#34;/home/apps/backup/demo.phalapi.com&#34;
  4. override=&#34;true&#34; /&gt;
  5. &lt;property
  6. name=&#34;backup_prefix&#34;
  7. value=&#34;demo.phalapi.com_phing_backup_&#34;
  8. override=&#34;true&#34; /&gt;
  9. &lt;property
  10. name=&#34;svn_todir&#34;
  11. value=&#34;./__svn__&#34;
  12. override=&#34;true&#34; /&gt;
  13. &lt;!-- ============================================ --&gt;
  14. &lt;!-- Target: rollback --&gt;
  15. &lt;!-- ============================================ --&gt;
  16. &lt;target name=&#34;rollback&#34; &gt;
  17. &lt;unzip file=&#34;${backup_path}/${backup_prefix}lastest.zip&#34; todir=&#34;.&#34; &gt;
  18. &lt;fileset dir=&#34;.&#34;&gt;
  19. &lt;include name=&#34;*.zip&#34;/&gt;
  20. &lt;/fileset&gt;
  21. &lt;/unzip&gt;
  22. &lt;/target&gt;

</project>

2.22.3 autobench:接口压力测试与可视化图表

可以通过以下的脚本来进行,使用示例:

  1. $ ./autobench.sh
  2. Usage: ./autobench.sh <host> <uri>
  3. - ./autobench.sh www.baidu.com /index.php

参数可以自行调整。

(1)利用bench2graph生成可视化图表

纯PHP访问 - 入口欢迎接口

a pic

mysql访问 - 事件获取接口

a pic

带MC缓存的访问 - 应用入口 - 带缓存的身份token验证

a pic

(2)详细的数据报表

  1. 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
  2. 5 5.0 5.0 4.8 5.0 5.2 0.1 22.4 2.9 0
  3. 25 25.0 25.0 25.0 25.0 25.0 0.0 21.6 14.3 0
  4. 45 45.0 45.0 45.0 45.0 45.0 0.0 22.3 25.7 0
  5. 65 64.9 64.9 64.7 64.7 64.7 0.0 25.4 37.0 0
  6. 85 84.8 84.8 84.6 84.6 84.6 0.0 28.6 48.3 0
  7. 105 104.6 104.6 0.0 0.0 0.0 0.0 34.4 59.7 0
  8. 125 124.0 124.0 0.0 0.0 0.0 0.0 42.2 70.7 0
  9. 145 143.8 143.8 0.0 0.0 0.0 0.0 59.2 82.0 0
  10. 165 147.4 147.4 0.0 0.0 0.0 0.0 262.9 84.1 0
  11. 185 151.1 151.1 0.0 0.0 0.0 0.0 429.7 86.2 0

(3)附脚本

  1. #!/bin/bash
  2. if [ $# -eq 0 ]; then
  3. echo "Usage: $0 <host> <uri>"
  4. echo ""
  5. echo " - $0 www.baidu.com /index.php"
  6. echo ""
  7. exit
  8. fi
  9. DM=$1
  10. URL=$2
  11. #--signle_host 只测单机
  12. #--host1 测试主机地址
  13. #--uri1 host1 测试URI
  14. #--quiet 安静模式
  15. #--low_rate 测试时最低请求数(指 httperf)
  16. #--hight_rate 测试时最高请求数
  17. #--rate_step 每次测试请求数增加步长
  18. #--num-call 每连接中发起联接数,一般是1
  19. #--num_conn 测试联接数
  20. #--file 测试结果输出的 tsv文件
  21. autobench \
  22. --single_host \
  23. --host1=$DM \
  24. --port1=80 \
  25. --uri1=$URL \
  26. --low_rate=5 \
  27. --high_rate=200 \
  28. --rate_step=20 \
  29. --num_call=1 \
  30. --num_conn=500 \
  31. --timeout=10 \
  32. --file ./$DM.tsv

2.22.4 xhprof:性能分析工具

xhprof是一个不错的内部性能分析工具,这里不过多的讲述此工具的特点和使用,但会以对PhalApi进行的一个性能测试展示它的分析效果。

(1)测试的接口服务

http://api.phalapi.com /demo/?service=Default.Index&username=test

(2)Overall Summary

  1. Total Incl. Wall Time (microsec): 7,873 microsecs
  2. Total Incl. CPU (microsecs): 7,999 microsecs
  3. Total Incl. MemUse (bytes): 304,456 bytes
  4. Total Incl. PeakMemUse (bytes): 306,616 bytes
  5. 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从中可以看出,主要的耗时途径在于文件的加载,下面将进一步探讨。

(4)Top 1耗时深入

a pic

所加载的文件如下:a pic

2.22.5 Jenkis和Sonar:持续集成和静态代码分析

PhalApi从来不会隐藏自己的设计,当然,我们也不会隐藏我们内部的各个细节以及存在的问题。但和其他隐藏了技术债务的框架相比,PhalApi敢于展示自己的静态代码分析报告,并且它也是做得相当出色的。

以下截图来自 GIT@OSC 上的静态代码分析:a pic

当你的项目很重要时,也可以使用Jenkis或者Sonar进行静态代码的分析。不要个人主观地觉得你的代码风格写得好,而是交由专业的分析工具进行解剖,并理解各个数据报表背后的含义,然后改进之。

2.22.6 Git/SVN:更多的版本控制

2.22.7 WIKI:团队沟通与文档交流

(1)markdown接口模板

  1. #3.2 接口文档模板
  2. ##1、功能说明
  3. _请在这里放置简短的接口功能说明。_
  4. ##2、接口URL
  5. /?service= _接口服务名称_ + 公共参数(是否免登录态?)
  6. ##3、接口参数 [跳转](http://demo.phalapi.com/demo/checkApiParams.php?service=)
  7. 参数|必须|默认值|说明
  8. ---|---|---|---
  9. user_id|1||用户id
  10. ##4、返回结果
  11. ###返回字段
  12. 参数|类型|说明
  13. ---|---|---
  14. data.username|string|用户名
  15. ###结果示例
  16. {
  17. "ret": 200,
  18. "data": {
  19. .... //更多结果的说明
  20. "msg": ""
  21. },
  22. "msg": ""
  23. }
  24. ###请求示例
  25. _请放置一个接口请求的链接。_
  26. http://demo.phalapi.com/demo/?service=

2.22.8 静态代码分析工具 - phpmetrics

以下是针对本框架核心代码所做的分析报告:

a pica pic

PS:从报告的评估可以看出,我们的框架明显具有相当 高的可维护性。

原文: https://www.phalapi.net/wikis/2-22.html