各开源框架使用与设计总结

一、框架课程总结

框架、设计模式和队列是5月份公开课的三个主题,第一周讲设计模式,第二、四周讲框架,第三周讲队列。框架讲了两周,介绍了框架的概念、PHP框架的应用范围,以及常用的PHP框架,今天是框架的最后一讲,是对整个框架系列课程的汇总,同时和大家讨论一些框架之外、或者框架之下的技术。


今天要讨论的分为这几个方面,总结框架系列课程、探讨框架可能存在,或者解决不了的问题,以及其解决方案和当前的探索。


在框架第一讲中,志华老师也站得高度很高,讲述了框架、架构的概念,以及对比了它的异同。总结来讲就是架构涉及到的是一个产品的性能、可扩展性之类问题。而框架则涉及到一个产品在实际的实现过程之中,所用的技术方案。比如性能和可扩展性,也就是架构所关系的内容,和底层语言其实关系不大。无论是PHP语言,还是Ruby语言,来实现一个大型网站,后端都可以部署数据库,数据库有主从,都需要缓存,缓存都可以是Memcached,数据库可以是MySQL。而框架则是我们做一个产品实现所用的具体技术实现方案,不但跟语言本身关系密切,而且涉及到在开发中的具体开发方案。打一个比喻,建造一个开发区。架构就是图纸,水、电、暖布局、楼盘、商业布局、容量布局,而框架则是细化的实施方案,这个写字楼是板楼还是塔楼,是做写字楼还是做酒店,前者与材料外观无关,后者则与材料外观相关。

再在后面的课程中,我们分别了解了Durpal、Symfony、ThinkPHP、YII、ZendFramework等框架的用法与扩展。

通过对框架的学习,我们认识到各自的框架都有自己的优势,使用框架带来了巨大的便利,比如很快构建起一个脚手架,英文叫Skeleton,有很多可用的方便工具和函数。当然,学习一套框架有成本,使用一套框架更有约束。也能看到框架的作用,可以归结为如下几点:

1、快速构建的脚手架,而不是从零开始

2、一套共同的约束和规则,保证开发质量。

3、工具和函数库、共同认识,无疑提高了开发效率

二、跳出PHP应用开发框架看框架

但是?今天我们从两个层次来看讨论问题。

第一个层次是高级的层次,我们简单看一下。在前面讲的,都基于PHP的应用开发框架而展开,即使我们讲了这么些框架,但这些框架也只是小部分代表,如果只站在应用的这个层次再多讨论也没有太大的意义。我们要跳出来看,就像,框架就是在应用开发这个层次吗?就只讨论PHP语言吗?他们的共同特点在哪里?

框架并不是局限于某个特定语言、或者特定用途东西。比如我们讲Web
开发框架,这个Web开发框架,可以是PHP的,也可以是Ruby语言写的,像Rubyon rails,甚至最近流近的 go
语言,也开始有自己的Web开发框架,甚至还有用
C语言去写的。而框架也不仅限于Web开发或者网站功能开发,有测试框架,像PhpUnit,JUnit这样的软件。像Thrift、ICE这样的,属于分布式通信框架。

共同特点,有几点:

1、都提供了自己领域内较完整强大的功能。(区别于函数库,比函数库更综合,更完整)。

2、都提供了自己领域内功能较具体的实现。(区别于架构这个较虚的概念)。

3、但是提供的是一些规范、脚手架。(区别于现成的产品,这只是一个特定领域的半成品)。

三、框架可能或者带来的问题

了解了框架在整个编程开发领域,大面上的感性认识,我们具体来探讨这两周公开课下来,框架所不能解决的问题。这是第二个层次,是更深入的层次。

1、第一个问题,就是开发习惯上的问题。如果团队决定采用一个框架。特别是全新的框架,就比较费劲了,可能还得有一个正式的培训阶段。

2、第二个问题,框架都有其适用的场景,需要架构师需要在什么阶段在合适的时候,采用合适的框架。

3、第三个问题,性能问题。大部分的框架,都用到了一些复杂的规则,比如ORM、比如模板引擎,这些东西,天生就是比较低效,尤其是像PHP这样的动态脚本语言。在企业系统、小流量的时候,还好,但是如果进入大流量时期,这个性能问题,就不容忽视了。

4、第四个问题,是扩展性问题。比如流量大了,数据库后端,也不再是一个数据库了,同一个数据类型也不再是一个数据表了。这个时候,框架有些地方,就该动动了。ThinkPHP那一讲上分享了这样的问题。

四、PHP性能的改进手段

好的,那我们来看一下,PHP业界,在提高框架性能、或者者整个PHP性能问题上,所做的一些探索。这也是我们今天的重点。

那么,我们想一想,你想提高PHP程序的效率,可以做哪些尝试?另外还有一个意思的事情是,你觉得,谁对提高
PHP程序的效率,最有动力?

第一、我们知道,PHP很容易写出很低效的程序,数据库频繁重连。写的查询很低效。某个函数实现,可能有问题等等。那么这些问题,需要有一个很好的手段去发现。这个时候,一个神器诞生了。这就是XHProf。XHProf是谁出的呢?Facebook,这是我们刚才讲的谁最有动力来提高PHP效率呢,谁在大规模的环境下,经常使用PHP,就最有动力。Facebook就最有这个动力了。

第二、上面讲的是第一个层次,先把PHP语言本身的一些东西给优化了。把第一个层次应用到框架上,就是我们通过XHprof可能发现了框架的一些性能瓶颈。第二个层次呢?我们再反问一下,提高程序性能最有效的方式是什么?我相信大部分同学都会提一个手段,缓存。没有错,第二个提升的层次就是缓存,我们将模板编译,是一种缓存方式,或者在库中,支持一些外部缓存,比如ThinkPHP
就是一个很典型的例子,支持模板编译缓存。也支持大量预置的Cache函数库。

第三个层次,有人就想了,PHP这种动态的脚本语言,在每一次运行时都是现编译解析,有没有一些办法,把这个每次编译解析的过程省了。这其实也经过了两个步骤。在CGI时代,每一个PHP页面的运行,所有的PHP模块都需要重新加载。每一个程序都有这个加载过程其实很浪费的。

因此就进入了mod_php 这个阶段,就是这张图

而再到后来改进成这张图,

再到后来,人们从PHP本身的编译过程上再省一步,加进了opcache,就是opcode
的cache,就是从PHP脚本编译成为操作码的缓存,这样的话,对程序,省去了第一个编译环节。

就成了这一张图

上面虚线的部分,就是缓存住了的,一个脚本只执行一次编译,后面的调用,都共享第一次编译所留下来的opcode缓存,APC就是一个实现opcode缓存的框架,同类的还有XCache,eAccelerator,我们今天的例子是用的zend
opcache。

上面说了这么多,这还只是第三个层次,其实还有三个层次的手段。

第四个层次,是将核心的,有瓶颈的业务逻辑,转到后端去实现。也就是说不用PHP了,举一个典型的例子,就是分库分表,连接池这样的功能,当然,分库分表,我们可以采用PHP来实现,但是连接池这样的功能就比较费劲一些了。所以一般对于一个高效的分布式架构来讲,这种逻辑会有一个DB
Proxy,来管理着客户端对服务器的长连接,PHP本身不再直接连接数据库,而是连接这个代理,由这个代理,来实现多表查询等操作。这里只是举一个例子。比如我们讲的缓存,甚至KVDB、全文检索,估计也有朋友写过PHP版存储和引擎,但是实际上在现实的使用中,还是更多的使用后端的服务。

第五个层次,就是一些大神出来了,他们受不了传统PHP,PHP框架的低效,开发模块,开发模块化的PHP框架。这个比较好理解。模块嘛,C语言实现,编译成二进制共享库,从Web
Server一启动就预加载。所以必然会高效一截。今天我们来看看Yaf、Phalcon这两C写的框架。也正好呼应咱们框架总结的这个主题。

第六个层次,我就该来问了?是不是PHP本身也是非常陈旧和低效了,是不是有改进的空间,甚至PHP重新用不一样的思路实现,可行不可行?这个问题,后面慢慢道来。

好的,是不是感觉有了一种全新的视角?我们回过来看看这些改进,在实际生产中的实现。

五、PHP性能改进在生产中的实践


5.1、XHProf

首先来看一下XHProf这个工具,怎么能改进我们的PHP语言本身。

首先安装这个工具,就是模块化安装。

我们封装一下操作类。

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

<?php

/**

 * 优才网公开课示例代码

 *

 * XHProf 封装类

 *

 * @author 伍星

 * @see http://www.ucai.cn

 */

 

class XHProf

{

 

    public
function __construct()

    {

        // start profiling

        $XHPROF_ROOT
= "/home/wwwroot/ucai_app/samples";

        include_once
$XHPROF_ROOT . "/xhprof_lib/utils/xhprof_lib.php";

        include_once
$XHPROF_ROOT . "/xhprof_lib/utils/xhprof_runs.php";

    }

 

    public
function beginProf()

    {

        xhprof_enable();

 

        register_shutdown_function(‘XHProf::endProf‘);

    }

 

    public
function endProf()

    {

        $xhprof_data
= xhprof_disable();

 

        $xhprof_runs
= new XHProfRuns_Default();

        $run_id
= $xhprof_runs->save_run($xhprof_data, "xhprof_foo");

 

        echo
"<a href=\"http://samples.app.ucai.cn/xhprof_html/index.php?run=$run_id&source=xhprof_foo\">性能分析结果</a>";

    }

 

}

  

值得注意的是这句话:

register_shutdown_function(‘XHProf::endProf‘);

什么意思呢,就是在整个页面完成了之后,输出结果报表链接。

5.2 、Opcache的安装与配置

其次我们来看看 opcache,安装过程没有什么讲的,主要是推荐一个配置,并且需要强调,opcache不是PHP extension,是zend
extension, 所以非常容易出错。配置如下:

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

[opcache]

zend_extension="/usr/local/php/lib/php/extensions/no-debug-zts-20090626/opcache.so"

opcache.enable_cli=1

opcache.memory_consumption=128      //共享内存大小, 这个根据你们的需求可调

opcache.interned_strings_buffer=8   //interned string的内存大小, 也可调

opcache.max_accelerated_files=4000  //最大缓存的文件数目

opcache.revalidate_freq=60          //60s检查一次文件更新

opcache.fast_shutdown=1             //打开快速关闭, 打开这个在PHP Request Shutdown的时候

                                    //   会收内存的速度会提高

opcache.save_comments=0             //不保存文件/函数的注释

5.3、Yaf和Phalcon

再次来看两个C语言写的PHP框架

第一个介绍的是Yaf 框架,这是一个纯C语言框架。具体的安装过程和实验如下:

1、从github 下载  php-yaf https://github.com/laruence/php-yaf

2、解压,按PHP模块的编译手法编译

?





1

2

3

4

5

6

7

phpize

./configure --with-php- /usr/local/php/bin/php-config

make

make install

  

3、在php.ini 中配置

?





1

2

3

4

5

extension = "yaf.so"

yaf.environ="product"

  

4、通过命令行上执行 php –m|grep yaf  你就能看到模块已经安装好了。

5、余下的就是Web测试。

在源码目录下,找到

?





1

2

3

php-yaf-master/tools/cg

./yaf_cg ucai_gkk

  

6、将output 目录下的 ucai_gkk 移至 samples.app.ucai.cn 所在的目录下,就可以通过 http://samples.app.ucai.cn/ucai_gkk

来访问。

7、我们可以做一下改造实验,了解一下这个框架的基本结构。

大家可以看到,我只是一通过一个工具,就生成了整个程序的框架,就可以根据需要,添加自己的业务逻辑。

比如 ,在models/Sample.php 中增加一个方法,

?





1

2

3

4

5

6

7

public function selectProductSample()

    {

        return
"<h1>Hello Haha</h1>";

    }

  

在 views 目录下新建文件,product/index.phtml

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

<?php

/**

 * 优才网公开课示例代码

 *

 * Yaf 视图

 *

 * @author 伍星

 * @see http://www.ucai.cn

 */

echo
$content, " I am ", $name, " From Product";

?>

  

在controllers 目录下建立 Product.php

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

<?php

/**

 * 优才网公开课示例代码

 *

 * Yaf 控制器

 *

 * @author 伍星

 * @see http://www.ucai.cn

 */

 

/**

 * @name IndexController

 * @author root

 * @desc 默认控制器

 * @see http://www.php.net/manual/en/class.yaf-controller-abstract.php

 */

class ProductController extends
Yaf_Controller_Abstract

{

 

    /**

     * 默认动作

     * Yaf支持直接把Yaf_Request_Abstract::getParam()得到的同名参数作为Action的形参

     * 对于如下的例子, 当访问http://yourhost/hello/index/index/index/name/root 的时候, 你就会发现不同

     */

    public
function indexAction($name
= "Product")

    {

        //1. fetch query

        $get
= $this->getRequest()->getQuery("get", "default value");

 

        //2. fetch model

        $model
= new SampleModel();

 

        //3. assign

        $this->getView()->assign("content", $model->selectProductSample());

        $this->getView()->assign("name", $name);

 

        //4. render by Yaf, 如果这里返回FALSE, Yaf将不会调用自动视图引擎Render模板

        return
TRUE;

    }

 

}

  

这样我们就可以通过,http://samples.app.ucai.cn/hello/?a=index&c=product

这样的链接来访问,我们新建的内容了。操作起来很简单。

用同样的方式,我们安装Phalcon。虽然从形式上,它更简单。通过目录就知道,内容更为丰富。

这也是Yaf跟Phalcon的很大的不同之处,Yaf尽管效率很高,但是要在生产上使用,还是略显单薄,功能不够丰富。而Phalcon则真的是功能很全的。正像优才网培养的叫全栈工程师,而Phalcon也号称自己是Full
Stack 的一个框架。

这次,没有工具来生成一个基本的框架,但是我们可以从Github上的一个教程,作为切入点。

https://github.com/phalcon/tutorial

下载了这个教程之后,我们就可以开始动手了。先看看功能 。

放到相应的目录下之后,比如 http://samples.app.ucai.cn
目录下之后,得配置一下rewrite 规则。

?





1

2

3

rewrite ^/phalcon/(.*?)$ /phalcon/public/index.php?_url=/$1
last;

rewrite ^/phalcon$ /phalcon/public/index.php last;

  

然后,通过 http://samples.app.ucai.cn/phalcon/
可以访问。

发现有一个注册功能,那我们就来想这个数据怎么保存的。

发现在 public/index.php 中有一段配置,

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

   //Set the database service

$di->set(‘db‘, function() {

       return
new \Phalcon\Db\Adapter\Pdo\Mysql(array(

           "host"
=> "127.0.0.1",

           "username"
=> "xxxx",

           "password"
=> "xxxxx",

           "dbname"
=> "xxxxxx"

       ));

   });

  

我们在这里改了配置了之后,再看看提交的情况。

发现在SignupControll.php 中有一段保存代码 ,

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

$user = new Users();

        $user->name = $name;

        $user->email = $email;

 

 

        //Store and check for errors

        if
(($userid
= $user->save()) == true)

        {

            echo
‘Thanks for register!‘;

        } else

        {

            echo
‘Sorry, the next problems were generated: ‘;

            foreach
($user->getMessages() as
$message)

            {

                echo
$message->getMessage(), ‘<br/>‘;

            }

        }

  

过去看这个 models/Users.php 却是空的?

我们在不修改Users.php的时候,看看是否能将数据保存进去?

当然前提是建一个表,因为我怀疑,这存在某种关系 的映射。

?





1

2

3

4

5

6

7

8

9

10

11

CREATE TABLE `users` (

  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,

  `name` varchar(70) NOT NULL,

  `email` varchar(70) NOT NULL,

  PRIMARY KEY (`id`)

);

  

发现果不其然,保存进去了,好,我们再进一步,找一现实中可能会用的表格格式,比如下划线的表格 users_exinfo。

?





1

2

3

4

5

6

7

8

9

10

11

CREATE TABLE `users_exinfo` (

  `id` int(10) unsigned NOT NULL default
0,

  `schoolname` varchar(70) NOT NULL,

  `age` int NOT NULL,

  PRIMARY KEY (`id`)

);

  

看看能否实现保存,于是乎也建了一个空类。

?





1

2

3

4

5

class UsersExinfo extends
Phalcon\Mvc\Model{

   

}

  

同时也修改了视图,将数据保存了进去。

结果如下:

大家看到,成功地保存了数据。

5.4、zephir高效开发模块


好的,讲到这里,衍生出一个小话题,就是开发模块。

在PHP里,开发模块,是一个很痛苦的过程。因为C语言,大家都知道,是出了名的难学的,值得高兴的是,也是Phalcon这个团队的童鞋们,也为我们准备了一个高效的开发模块的语言,称之为zephir。正因为扩展如此难以开发,但是扩展又是如此高效,所以我们要用高效的方式来开发扩展。

?





1

2

3

4

5

git clone
https://github.com/phalcon/zephir.git

cd zephir/

mv zephir /usr/local/

  

然后就可以开发模块了,我们使用

zephir init gkk

生成模块的框架,

然后 cd gkk/gkk

编写 hello.zep

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

namespace
Gkk;

 

/**

 * This is a sample class

 */

class Welcome

{

    /**

     * This is a sample method

     */

    public
function welcome()

    {

        echo
"你们好!参加优才网公开课的同学们!";

    }

 

    public
function say()

    {

        echo
"今天是优才网第三十三讲公开课了!";

    }

 

 

}

  

然后再返回

zephir compile

zephir build

然后在 php.ini 中配置

extension=gkk.so

通过 php –m 可以看到相应的模块。再编写

?





1

2

3

4

5

6

7

8

9

10

11

12

13

test.php

<?php

 

$t
= new Gkk\Welcome();

$t->say();

echo
"\n";

?>

  

就能看到相应的输出。

5.5、各框架性能总结


好的,有关两个用C开发的框架和相关内容我们就介绍到这里。下面我们来总结一下框架,以及做一些性能评测。

首先来看一下性能评测报告,这是一个专门测框架的github项目出的数据,

博客在这里,

?https://github.com/eryx/php-framework-benchmark

从上面的图可以看到,两个用C编写的框架,性能还是相当可观的。Yaf比Phalcon性能更强,也不奇怪。因为结构更为简单,模块更少。同时也发现,像zend
framework这样的框架,是不能轻易在一个大众的互联网产品中使用的,尽管代码写得不错,但是效率太低了,有木有!

5.6、PHP的重写

在评测之前,大家记起来了没有,我们上面讲了六点,其中有一点是什么?重写PHP!

那就看看,哪些业界人士,在PHP重写的路子上做了非常激动人心的尝试。

刚才讲了,谁最有动力?

有两个方面的人有动力,一个是PHP最大的使用者,一个是PHP官方。最大的使用者,他对PHP的提升,能大幅度地减少资源的占用,一个百分之几的优化可能就是成百上千台设备的节省。而后者,则要想到如果PHP本身效率提升不上去,在未来的发展过程中,很容易出现转折,尽管现在还是非常火的。

所有从官方,就有了,PHPng,这个我没有安装过,有兴趣的同学,可以自己去折腾,https://wiki.php.net/phpng
值得一提的是,咱们国内的鸟哥是这个项目的主要参与者之一。Yaf也是他的作品。而另外一个,则是Facebook主导的,HHVM,其前身是HipHop,
当时的思路是把PHP全部编译成C++程序,在上线的过程中,上线的是一个二进制包,非常不灵活,修改代码,需要发包才能生效。如果出现故障,会有灾难性的影响。所以演进到现在成了HHVM,全称是HipHop
Virtual Machine。

现在的模式,简单了讲就是可以做为FastCGI 的运行容器。大家安装过LNMP的同学就知道,在Nginx的后端,也就是说Nginx的配置中,通过

fastcgi_pass  这个配置指向了实际运行PHP的FastCGI 运行容器,PHP自带的是PHP-FPM(FastCGI Process
Manager),而HHVM就是可以一定程度上无缝地替换掉,FPM,比如你kill掉FPM进程,通过

hhvm --mode server -vServer.Type=fastcgi -vServer.Port=9000 &

来启动HHVM。都不需要修改nginx 配置。就可以访问了。

但是性能一定程度上,大有提升。

这枚神器有如下特点:

?当然不是小团队能玩的

?与PHP 5.2引擎+APC相比,可以处理的Web请求吞吐量增加了9倍,而内存消耗减少了5倍。

?如无特殊模块,可以无缝替换 php-fpm(除了极少数兼容问题)

?1、优点

–FB出品

–强大到令你吃惊,数十倍的性能提升

–已经趋于稳定,无缝替换 PHP-FPM

?2、缺点

–还不是很稳定

–模块需要迁移

六、各项实践,性能评测


下面进入性能评测,评测我们相对就比较快速一些。直接用ab命令,来测试上面的所提及的一些改进。

以下评测,所有测试页面,均为:http://hjvote.app.ucai.cn/index.php
命令行为:

ab -c 20 -n 1000 http://hjvote.app.ucai.cn/index.php

6.1 、冷启动


1、冷启动,比如我新启动的php-fpm,关掉opcache,关掉xhprof

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

Concurrency Level:      20

Time taken for
tests:   4.981 seconds

Complete requests:      1000

Failed requests:        0

Write errors:           0

Total transferred:      478000 bytes

HTML transferred:       109000 bytes

Requests per second:    200.78 [#/sec] (mean)

Time per request:       99.612 [ms] (mean)

Time per request:       4.981 [ms] (mean, across all concurrent requests)

Transfer rate:          93.72 [Kbytes/sec] received

  

6.2、第二次

2、第二次,条件同上。

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

Concurrency Level:      20

Time taken for
tests:   4.537 seconds

Complete requests:      1000

Failed requests:        0

Write errors:           0

Total transferred:      478000 bytes

HTML transferred:       109000 bytes

Requests per second:    220.42 [#/sec] (mean)

Time per request:       90.736 [ms] (mean)

Time per request:       4.537 [ms] (mean, across all concurrent requests)

Transfer rate:          102.89 [Kbytes/sec] received

  

6.3、打开opcache第一次

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

Concurrency Level:      20

Time taken for
tests:   1.591 seconds

Complete requests:      1000

Failed requests:        0

Write errors:           0

Total transferred:      478000 bytes

HTML transferred:       109000 bytes

Requests per second:    628.67 [#/sec] (mean)

Time per request:       31.813 [ms] (mean)

Time per request:       1.591 [ms] (mean, across all concurrent requests)

Transfer rate:          293.46 [Kbytes/sec] received

  

6.4、第二次,条件同上

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

Concurrency Level:      20

Time taken for
tests:   1.254 seconds

Complete requests:      1000

Failed requests:        0

Write errors:           0

Total transferred:      478000 bytes

HTML transferred:       109000 bytes

Requests per second:    797.70 [#/sec] (mean)

Time per request:       25.072 [ms] (mean)

Time per request:       1.254 [ms] (mean, across all concurrent requests)

Transfer rate:          372.36 [Kbytes/sec] received

  

6.5、对比再打开xhprof

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

Concurrency Level:      20

Time taken for
tests:   1.254 seconds

Complete requests:      1000

Failed requests:        0

Write errors:           0

Total transferred:      478000 bytes

HTML transferred:       109000 bytes

Requests per second:    797.44 [#/sec] (mean)

Time per request:       25.080 [ms] (mean)

Time per request:       1.254 [ms] (mean, across all concurrent requests)

Transfer rate:          372.24 [Kbytes/sec] received

  

6.6、打开XHprof,关掉Opcache


对于这个简单的页面,没有明显恶化,我们去掉Opcache,打开xhprof

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

Concurrency Level:      20

Time taken for
tests:   12.103 seconds

Complete requests:      1000

Failed requests:        0

Write errors:           0

Total transferred:      595000 bytes

HTML transferred:       226000 bytes

Requests per second:    82.62 [#/sec] (mean)

Time per request:       242.065 [ms] (mean)

Time per request:       12.103 [ms] (mean, across all concurrent requests)

Transfer rate:          48.01 [Kbytes/sec] received

  

6.7、第二次、条件同上

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

Concurrency Level:      20

Time taken for
tests:   9.298 seconds

Complete requests:      1000

Failed requests:        0

Write errors:           0

Total transferred:      595000 bytes

HTML transferred:       226000 bytes

Requests per second:    107.55 [#/sec] (mean)

Time per request:       185.952 [ms] (mean)

Time per request:       9.298 [ms] (mean, across all concurrent requests)

Transfer rate:          62.50 [Kbytes/sec] received

  

在没有opcache的情况下,XHProf的加入,导致用户急剧变慢。

6.8、关掉xhprof  HHVM第一次

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

Concurrency Level:      20

Time taken for
tests:   1.142 seconds

Complete requests:      1000

Failed requests:        0

Write errors:           0

Total transferred:      521000 bytes

HTML transferred:       109000 bytes

Requests per second:    875.84 [#/sec] (mean)

Time per request:       22.835 [ms] (mean)

Time per request:       1.142 [ms] (mean, across all concurrent requests)

Transfer rate:          445.62 [Kbytes/sec] received

  

6.9、 第二次,条件同上

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

Concurrency Level:      20

Time taken for
tests:   0.852 seconds

Complete requests:      1000

Failed requests:        0

Write errors:           0

Total transferred:      521000 bytes

HTML transferred:       109000 bytes

Requests per second:    1173.42 [#/sec] (mean)

Time per request:       17.044 [ms] (mean)

Time per request:       0.852 [ms] (mean, across all concurrent requests)

Transfer rate:          597.03 [Kbytes/sec] received

  

什么感觉?这种数字的差距是不是可以用震撼来形容?通过评测对比,我们对于opcache、hhvm和一般php-fpm性能心里也就有数了。同时也发现,在页面上开启XHProf,会导致网页性能急剧下降,所以不要在生产环境对多人开启XHProf。或者会带来非常不好的用户体验。

七、自有框架的设计


好的,看完了性能评测,我们来过了一下如果设计一个自有的框架需要哪些元素,或者说需要哪些内容。

1、首先对目录结构进行一个划分,确定目录层次结构

–app    命令行应用

–data   存放数据上传

–lib 库函数

–template  模板

–conf   各种配置

–doc    文档,SQL

–log     日志

–test    测试代码

–ctemplate 编译后的模板

–htdocs     Web主目录

大家能看到,htdocs 同其他目录,比如
doc、app目录为什么要并列?这是安全性的考虑,想一想,否则的话,你的表定义被人下走了。你的后台程序,可能会被用户执行。

2、其次来看一下类的层次结构。

下图是应用程序各个类的分层。

最基层的应用程序类,其实就是一个骨架。包括了getParam(取得参数,无论命令行,还是Web访问,都需要有参数分析)。checkParam(参数检测)、checkAuth(权限检测,比如是否是需要登录的一个页面)、outputPage等这些方法,全是空方话,但是由一个run方法串起来。如下:

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

public function run()

      {

          

           $this->getPara();

 

           $this->checkPara();

          

           $this->checkAuth();

 

           $this->main();

          

           $this->outputPage();

 

           $this->exitApp();

      }

  

应用程序基类DCore_BaseApp.php的子类又分为三个,一个负责命令行程序的处理DCore_ConsoleApp.php,另外一个负责像移动应用、开放平台Api之类的数据处理DCore_ApiApp.php
,而第三个,则是DCore_WebApp.php,
我们所在浏览器上所访问的应用,由这个应用程序类派生出来页面类。而DCore_AdminApp.php,是管理后台应用程序类的基类。因为后端一般有不一样的权限认证机制。这样也是为了把前后台的应用程序类区分得更加清楚。

这样可以看到,整体结构非常清晰。

好,那最后我们再来看一下,需要编写哪些类库。

在我们的框架中,编写了这些。

?1、常用工具函数库

实现字符串的常用操作封装,比如中文取字串,繁简转换、编码转换

?2、模板引擎

可以简化为包含PHP,在我们自己开发的这个框架中,支持了模板编译,其实模板编译很简单,就是将一些特定的语法,换成PHP代码,然后还是包含PHP

?3、路由控制,静态化

用户可以将路径改成搜索引擎更友好的路径,程序也能解析正确。

?4、后端数据请求控制

用于对后端一些公用操作的封装,比如数据库,比如Memcached,这样的封装带来的好处是,如果一旦发生升级或者替换的时候,修改的代码相对最少。比如你不用到处去改mysql_query,只需要修改当前这个库文件即可以了。

八、总结


好的,今天的课程就到这里。总结一下,我们讲了如下几点:

1、5月课程尤其是5月份框架课程的总结。总结了框架与架构的区别。

2、站在PHP框架之外,看框架,看框架的共同特征与功用。

3、以PHP框架为例,讲框架所不能解决或者带来的问题。

4、由于框架所带来的问题,以性能、可扩展问题,相对严重,所以分析PHP性能 的改造方向,总结了六大点。

5、分别演示了这六大点的改进实践。包括Yaf、Phalcon框架介绍,zephir的使用,以及HHVM。

6、汇总六大点的改进,并做了相关的性能评测。能看到,使用不同的技术差别巨大,所以我们要在稳定可靠的情况下,尽可能采用最好的技术。

7、最后讲解了开发一个自有框架,一般都是一个什么样的思路。

各开源框架使用与设计总结,布布扣,bubuko.com

时间: 2024-10-06 01:19:44

各开源框架使用与设计总结的相关文章

各开源框架使用与设计总结(二)

原文详见:http://www.ucai.cn/blogdetail/7032?mid=1&f=5 可以在线运行查看效果哦! 5.4.zephir高效开发模块 好的,讲到这里,衍生出一个小话题,就是开发模块. 在PHP里,开发模块,是一个很痛苦的过程.因为C语言,大家都知道,是出了名的难学的,值得高兴的是,也是Phalcon这个团队的童鞋们,也为我们准备了一个高效的开发模块的语言,称之为zephir.正因为扩展如此难以开发,但是扩展又是如此高效,所以我们要用高效的方式来开发扩展. git clo

《自己动手写框架9》:理想的开源框架与设计原则

理想的开源框架?她应该是小的.简单的,满足Simple Is Beautiful?她应该是成长性好的,随着不断的扩展,她可以越来越丰满?她应该是有良好工具支持的,为什么要花时间做工具可以完成的事情呢??她应该是自组装的,也就是尽可能的脱离配置,而是用一种依赖即可用,取消依赖即消失的全自动处理模式?她应该是模块化的,所有的内容都可以被打入jar包而作为一个整体进行发布,并且能支持热部署的,可以开着车儿换轮胎的?她应该是支持水平部署的,想加服务器就加,想减服务器就减?她应该是有良好知识积累体系的,使

《开源框架那些事儿12》:框架2.0的设计梳理

前面从各个角度,讲了大概11篇了.言归正传,这里讲解一个完整的框架设计实例.这里不是一个空白的描述,而是基于V1.0之后的建构.因此,整个设计过程,也会尽量少走一些弯路.一起来看看吧! 方法论 方法论决定了可以达到的高度 方法论,就是人们认识世界.改造世界的根本方法. 它是人们用什么样的方式.方法来观察事物和处理问题.概括地说,世界观主要解决世界"是什么"的问题,方法论主要解决"怎么办"的问题. 方法论是一种以解决问题为目标的体系或系统,通常涉及对问题阶段.任务.工

《开源框架那些事儿27》悠然乱弹:一段SQL引发的性能危机及其背后隐藏的设计缺

有个同学,说是系统中出现性能问题了,说是让我帮助诊断一下.本来是不想花这时间的,结果耐不住对方的死缠乱打,只要答应帮看看.  故事发生的背景是,在文件上传的时候,有时间会有人上传了文件,但是最后没有使用上传的文件,这样就会产生一些垃圾文件. 原来软件作者就想写一个后台定时任务程序,来清除这些垃圾文件? 由于作者坚定的不让我发她的SQL语句(这个我也理解,这么丑陋的SQL),所以这里就不发源代码了,发伪代码. 123456789101112131415 void deleteMissLinkFil

《开源框架那点事儿25》:对框架模板引擎实现方式的改造实录

点滴悟透设计思想,Tiny模板引擎优化实录! 增加框架设计兴趣小组:http://bbs.tinygroup.org/group-113-1.html Tiny模板引擎的实现方式原来是採用的编译方式,近期发生了一些问题.因此我认为有必要把编译方式调整为解释方式,为此就開始了此次实现活动. 编译方式存在的问题 当时採用编译方式.主要是考虑到编译方式在执行时不必再去遍历语法树.因此就採用了编译方式. 可是在实际应用其中,出现了例如以下问题: 文件路径冲突的问题 因为採用的是编译方式,这个时候就存在在

六款值得推荐的android(安卓)开源框架简介

1.volley 项目地址 https://github.com/smanikandan14/Volley-demo (1) JSON,图像等的异步下载: (2) 网络请求的排序(scheduling) (3) 网络请求的优先级处理 (4) 缓存 (5) 多级别取消请求 (6) 和Activity和生命周期的联动(Activity结束时同时取消所有网络请求) 2.android-async-http 项目地址:https://github.com/loopj/android-async-http

Android酷炫实用的开源框架(UI框架)

前言 忙碌的工作终于可以停息一段时间了,最近突然有一个想法,就是自己写一个app,所以找了一些合适开源控件,这样更加省时,再此分享给大家,希望能对大家有帮助,此博文介绍的都是UI上面的框架,接下来会有其他的开源框架(如:HTTP框架.DB框架). 1.Side-Menu.Android分类侧滑菜单,Yalantis 出品.项目地址:https://github.com/Yalantis/Side-Menu.Android2.Context-Menu.Android可以方便快速集成漂亮带有动画效果

iOS开发-常用第三方开源框架介绍(你了解的ios只是冰山一角)

iOS开发-常用第三方开源框架介绍(你了解的ios只是冰山一角) 2015-04-05 15:25 2482人阅读 评论(1) 收藏 举报开源框架 图像: 1.图片浏览控件MWPhotoBrowser       实现了一个照片浏览器类似 iOS 自带的相册应用,可显示来自手机的图片或者是网络图片,可自动从网络下载图片并进行缓存.可对图片进行缩放等操作.      下载:https://github.com/mwaterfall/MWPhotoBrowser目前比较活跃的社区仍旧是Github,

《开源框架那点事儿18》:为什么要先从测试用例编写和文档编写开始?

有一个同学,问我一个问题:加入Tiny是否必须从写单元测试用例和文档作起? 此问题引发我诸多感触,故形成乱弹一篇. 作为一个新加入者,多看.少说,是正点.而这个时候,写写测试用例.文档,就是个不错的选择.这样入手比较容易,也比较容易体现水平. 可以说好的程序员,测试和文档都是写得好的.测试和文档一定写不好的,一定不是好的程序员. 同时,在看代码,写测试用例.写文档的过程中,还可以这样思考: 他为什么要这么设计?换成我,我会怎么设计?然后有相当一部分,会转化成:哦,原来是这个样子的!这个时候你进步