- 测试条件: I3 380M + 4G + Windows7 + iis7 + PHP5.4(fastcgi) + Zend2.3
- 网站设置: 使用默认的模块和控制器,配置config和module缓存. 不连接任何服务和数据库.为避免带宽不足清空view
- 测试软件: Jmeter 20并发用户.测试机和被测试机是不同的电脑,它们之间用100M5类线直连
在测试结果中,平均响应时间需要0.637秒,每秒处理30个请求.这个数据比zf1低一半. 同一台机zf1可以达到每秒60多个请求
我看到这个测试结果后有点想放弃zf2,可是在开发灵活和便捷性上zf2确实要比zf1要好得多. 分析发现,在zf2中路由,派遣和服务注册,模块注册拖累了整个速度. 以前做项目用到过yaf,发现yaf性能挺好的,于是计划用yaf代替zf2的mvc模块.
一. 在yaf项目中加载zf2类库
首先你得有一个能正常运行的yaf项目.在这个基础上改动以增加zf2支持.可以参考yaf官方教程做一个yaf的基本架构站点. 这里假设你已按照官方教程架设好yaf站点
1. 在yaf项目中使用composer
yaf官网示范中默认没有zf2的类加载器,考虑到今后还要加载其它的类库代码,这里使用composer加载zf2依赖. 要在yaf项目中引用composer需要对yaf项目的/public/index.php和/conf/application.ini做少量改动.
bootstrap()
->run();
改动后的文件和yaf默认文件主要的区别:
- 要增加chdir(dirname(__DIR__)). 目的是让zf2能正常读取配置文件
- require ‘init_autoloader.php’; 这个文件是在ZendSkeletonApplication.zip中复制出来的,目的是引用composer, zf2类库就要通过这个文件加载进来.
- $app->bootstrap() 必须要有引导器,因为后面要在bootstrap里面加载zf2配置和服务
因为yaf默认会禁用spl加载器,这会造成无法加载非yaf前缀命名的类.所以我们还需要更改yaf运行配置.在/conf/application.ini中设置 application.system.use_spl_autoload = true
[product]
application.directory = APP_PATH "/application/"
application.dispatcher.catchException = true
application.system.use_spl_autoload = true
总结一下,你需要更改 index.php,application.ini增加init_autoloader.php文件,哦!别忘记了编辑composer.json在其中增加zf2依赖配置. 我这里用的是zf2.3. 然后更新composer依赖. 等待composer依赖更新完成后测试项目,看看在yaf项目中是否可以用zf2的类库,这里应该可以引用,如果还是不行就请下载本文后面提供的完整代码.
add('Zend', $zf2Path);
} else {
include $zf2Path . '/Zend/Loader/AutoloaderFactory.php';
Zend\Loader\AutoloaderFactory::factory(array(
'Zend\Loader\StandardAutoloader' => array(
'autoregister_zf' => true
)
));
}
}
if (!class_exists('Zend\Loader\AutoloaderFactory')) {
throw new RuntimeException('Unable to load ZF2. Run `php composer.phar install` or define a ZF2_PATH environment variable.');
}
"require": {
"php": ">=5.3.3",
"zendframework/zendframework": "2.3.*"
}
2. 让Yaf项目中的zf2配置文件起作用
上面的改动完成后在yaf中可以使用zf2的类库了,这还不够,我们还要在项目中使用zf2的框架配置和服务管理器. 在改动前需要先了解yaf的限制.
yaf是c语言写的mvc框架,配置文件默认是applicatin.ini. yaf并不像zf2那样包含各种功能模块,特别是yaf不能直接使用zf2的配置文件.也就是说zf2的配置在yaf上是没有效果的.为了让zf2配置起作用,我们需要在yaf中调用zf2的服务管理模块以读取配置, 然后把配置好的服务模块注册到yaf_register中.
zf2如果除开mvc模块(这里我们用yaf代替了zf2-mvc),最核心的就是servermanager。所有的配置项,所有的服务类,包括事件等都是由servermanager管理,如需在yaf中使用zf2配置,就要把servermanager移植到yaf中. 在zf2中servermanager是最先被执行的,并且把实例作为参数由各种后续对象传递,在yaf中我们使用yaf_regisger传递servermanager实例. 由于我们用yaf代替了zf2的mvc模块,所以在我们移植后的项目中zf2配置中的mvc部分是没有作用的
我们先把zf2的配置文件复制到/conf中,注意zf2配置文件默认在/config目录,而yaf配置是在/conf中,为了让配置文件能正常工作,请把zf2应用配置文件application.config.php中的config_glob_paths配置文件路径由/config改为/conf. 除此以外其它的配置项不需要做任何更改.
接下来需要改动yaf的Bootstrap.php文件,还记得index.php中的bootstrap()么?,那就是为了运行这个文件准备的. 在这个文件中所有_init开头的方法都会被自动执行,我们把注册servermanager和读取zf2配置的方法写在这里,这样yaf项目启动的时候配置文件就起作用了. 然后在这里把通过配置生成的servermanager对象注册给yaf_regisger.这样在整个yaf中就可以像zf2那样使用服务管理器调用各种功能(不能调用mvc相关模块).
getConfig();
Yaf_Registry::set("config", $config);
}
public function _initServiceManager() {
$configuration = require APP_PATH . '/conf/application.config.php';
$smConfig = isset($configuration['service_manager']) ? $configuration['service_manager'] : array();
$serviceManager = new ServiceManager(new ServiceManagerConfig($smConfig));
$serviceManager->setService('ApplicationConfig', $configuration);
$configListener = new ConfigListener(new ListenerOptions($configuration['module_listener_options']));
// If not found cache, merge config
if (!$configListener->getMergedConfig(false)) $configListener->onMergeConfig(new ModuleEvent);
// If enabled, update the config cache
if ($configListener->getOptions()->getConfigCacheEnabled() &&
!file_exists($configListener->getOptions()->getConfigCacheFile())) {
$configFile = $configListener->getOptions()->getConfigCacheFile();
$content = "getMergedConfig(false), 1) . ';';
file_put_contents($configFile, $content);
}
$serviceManager->setService('config', $configListener->getMergedConfig(false));
Yaf_Registry::set('ServiceManager', $serviceManager);
}
public function _initSessionManager() {
Yaf_Registry::get('ServiceManager')->get('Zend\Session\SessionManager');
}
public function _initPlugin(Yaf_Dispatcher $dispatcher) {
$user = new UserPlugin();
$dispatcher->registerPlugin($user);
}
}
二. 在yaf项目使用zf2服务管理器调用数据库,cache,日志
调用各种zf2的服务功能时,需要先确保你的zf2配置中有对应的设置,具体设置参考zf2官方手册,本文后面也有示例代码下载.
n)) {
$session->n = 0;
}
$session->n++;
echo $session->n;
$adapter = $this->getDbAdapter();
$table = new TableGateway('admin', $adapter);
$entities = $table->select();
foreach ($entities as $entity) {
var_dump($entity->username);
}
$cache = $this->getStorage();
$cache->setItem('asdfas', 'asdfasdf');
$this->getLogger()->alert('asdfasd');
$this->getView()->assign("content", "Hello World");
}
/**
* db adapter
* @return \Zend\Db\Adapter\Adapter
*/
public function getDbAdapter() {
return Yaf_Registry::get('ServiceManager')->get('Zend\Db\Adapter\Adapter');
}
/**
* storage
* @return \Zend\Cache\Storage\StorageInterface
*/
protected function getStorage() {
return Yaf_Registry::get('ServiceManager')->get('Zend\Cache\Storage\StorageInterface');
}
/**
* logger
* @return \Zend\Log\Zend\Log\Logger
*/
protected function getLogger() {
return Yaf_Registry::get('ServiceManager')->get('Zend\Log\Logger');
}
}
三. 测试yaf集成zf2后的性能
我们使用jmeter测试改动后的yaf项目性能,测试条件和参数与上次测试zf2相同,结果如下:
现在测试数据好看多了,平均响应时间提高到81毫秒, 每秒响应请求数提高到241个. 其实我还测试过没有集成zf2服务管理器的yaf性能,每秒请求数可以达到1200(这是11年的I3移动版CPU的老笔记本电脑,每秒1200已经很强了),但是不提供服务的项目性能再好都没有意义.
这是一个完整的yaf集成zf2的项目示例.下载后请把把其中的dist配置文件复制并去掉.dist扩展名.yaf-sample-d771c9a.tar
Leave a Reply