内容简介:php框架的功能通用的路由,autoload。服务端mysql封装,日志组件。前端的页面渲染(smarty封装个)。在工作时听说别的部门换框架性能提升,所以调研了下常见的框架,包含ci,laravel,yii,yaf,会介绍下功能,另外给出号称最快框架yaf和常用yii和裸写框架的性能差。另外想实现rpc并发,http一般用过multi_curl可以,公司用的thrift没有实现并发,所以研究了下php协程,curl_multi,swoole异步,rpc中并发实现,corotine等。裸写在CPU占用方面和
php框架的功能通用的路由,autoload。服务端 mysql 封装,日志组件。前端的页面渲染(smarty封装个)。在工作时听说别的部门换框架性能提升,所以调研了下常见的框架,包含ci,laravel,yii,yaf,会介绍下功能,另外给出号称最快框架yaf和常用yii和裸写框架的性能差。另外想实现rpc并发,http一般用过multi_curl可以,公司用的thrift没有实现并发,所以研究了下 php 协程,curl_multi,swoole异步,rpc中并发实现,corotine等。
常用php框架提供功能
- ci http://codeigniter.org.cn/use...
Route.
autoload.载入文件正常controller 中load->helper(xx)。直接用xx
log. db. hook.公共函数。
代码逻辑分层。
ui抽象。模板。 -
laravel https://laravel-china.org/doc...
路由
中间件(前置后置)
配置区分环境,本地和线上密码不放其中
数据库 创建表,编辑,删除,迁移,回滚,软删除和恢复(标记删除位)。ORM链式操作
依赖注入,依赖自动发现。
IOC 平时的if new 这种工厂模式,IoC模式看作工厂模式的升华,以前在工厂模式里写死了的对象,IoC模式 改为配置XML文件,这就把工厂和要生成的对象两者隔离 类(DatabaseQueue,queue,QueueContract),serviceprovider(外部调这个)=>bind(将类绑定到容器)。调用Queue::xx。依赖注入可以直接调用$类->method。通过门面可以类::method 【https://www.cnblogs.com/shiwenhu/p/6882340.html】
事件
事件映射protected $listen = [ 'App\Events\OrderShipped' => [ 'App\Listeners\SendShipmentNotification', ],]; 写事件OrderShipped,写监听SendShipmentNotification 可以继承队列 分发事件:public function ship($orderId) { order=Order::findOrFail(orderId); // 订单的发货逻辑... event(new OrderShipped($order)); }
队列 ,redis,db, 广播
js监听
任务调度 只是cron
-
yii https://www.yiichina.com/doc/...
功能全面读介于ci和 laravel 之间,前端支持功能丰富。组件和行为是它的特色
行为
要定义行为,通过继承 yii\base\Behavior 。覆盖其中的events方法, public function events() { return [ ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate', ]; } public function beforeValidate($event) { // 处理器方法逻辑 }, 附加行为:lass User extends ActiveRecord { public function behaviors() { return [ [ 'class' => MyBehavior::className(), 'prop1' => 'value1', 'prop2' => 'value2', ]]}}或者attach组件就可以使用行为了。
直观感受下
- yaf http://www.laruence.com/manua...
php的一个扩展,因为是扩展,所以可以常驻内存,不用每次加载框架了、实现了基本功能
路由,
插件可以在几个hook处调用,比如自己开发一个Log,在这些Hook的地方加入回调( https://github.com/akDevelope... )
autoload
配置
yaf,cii,裸写框架(autoload,路由)代码和性能
性能比较
裸写在CPU占用方面和YAF相近,略高,在内存方面更节省。在吞吐量方面和YAF相近,略好。
CI框架会比YAF在CPU方面多耗费10%。吞吐量要差75%
- 吞吐
裸写优于yaf,yaf可以比CI提升75%左右
在php-fpm固定为10个,看处理速度,全部打满4000qps压测。10s预热,30s压测
我们的框架最大吞吐量是2200/s,平均有970,一共处理了20万
ci的最大为1850/s。但是会有502和504且有CPU为0的时候,平均只有400,一共处理5万左右,可以看出ci在稳定情况下最大的吞吐量可以达到1600,共处理4万左右
yaf的最大吞吐量是2280/s。但平均只有670,所以一共处理7万 - CPU
php-fpm开2048个,全部绑定到cpu1上, tsung压直到打满CPU,10秒预热+30秒压测
yaf和我们的框架可以压到600qps.CI到600直接CPU掉底了
500时,我们的框架略优于YAF.YAF相比于CI要节省至少10个点的CPU使用率
300时,我们的框架和YAF基本一样,CI还是要高出10个点。
代码
-
yaf
index.php <?php define('APPLICATION_PATH', dirname(__FILE__)); $performance = getrusage(); $globalPerformStatics['cpu_time_start'] = $performance['ru_utime.tv_sec'] *1000000+ $performance['ru_utime.tv_usec']+$performance['ru_stime.tv_sec'] *1000000+$performance['ru_stime.tv_usec']; $application = new Yaf_Application( APPLICATION_PATH . "/conf/application.ini"); $application->bootstrap()->run(); $performance = getrusage(); $globalPerformStatics['cpu_time_end'] = $performance['ru_utime.tv_sec'] *1000000+ $performance['ru_utime.tv_usec']+$performance['ru_stime.tv_sec'] *1000000+$performance['ru_stime.tv_usec']; var_dump($globalPerformStatics['cpu_time_end']-$globalPerformStatics['cpu_time_start']); ?> ———————————————————————————————— Bootstrap.php <?php class Bootstrap extends Yaf_Bootstrap_Abstract { public function _initRoute(Yaf_Dispatcher $dispatcher) { $router = Yaf_Dispatcher::getInstance()->getRouter(); $route = new Yaf_Route_Rewrite( 'order/base/passenger/getinfo', array( 'controller' => 'Base_Passenger_Getinfo', ) ); $router->addRoute('html1asdfd', $route); } public function _initView(Yaf_Dispatcher $dispatcher) { Yaf_Dispatcher::getInstance()->autoRender(false); } } ———————————————————————————————— 创建controller/Base/Passenger/Getinfo.php <?php class Base_Passenger_GetInfoController extends Yaf_Controller_Abstract { public function indexAction($name = "Stranger") { echo "hello"; $orderId = $this->getRequest()->getQuery("order_id"); $model = new SampleModel(); $orderInfo = $model->selectSample($orderId); var_dump($orderInfo); return TRUE; } } ———————————————————————————————— 创建Model <?php /** * @name SampleModel * @desc sample数据获取类, 可以访问数据库,文件,其它系统等 * @author */ class SampleModel { public function __construct() { } public function selectSample($id) { $a = $id / 5.314; // 取反正切 0-5.314的变化区间 $b = 1000 / 1.520837931073; return intval((100 / $a) * $b); } public function insertSample($arrInfo) { return true; } }
-
裸写
index.php <?php define('FRAMEPATH', '/home/project/phputil/'); define('APPPATH', '/home/project/order/'); $performance = getrusage();echo 1; $globalPerformStatics['cpu_time_start'] = $performance['ru_utime.tv_sec'] *1000000+ $performance['ru_utime.tv_usec']+$performance['ru_stime.tv_sec'] *1000000+$performance['ru_stime.tv_usec']; $appNameSpace = 'Project\Order'; $_GET = array_merge($_GET, $_POST);//fix Android端把$_GET改成$_POST问题 require_once(FRAMEPATH . '/autoload/autoloader.php'); $loader = Project\Autoload\Autoloader::getLoader(); $loader->addPsr4('Project\Order\\', APPPATH); require_once(FRAMEPATH . '/framework.php'); $performance = getrusage(); $globalPerformStatics['cpu_time_end'] = $performance['ru_utime.tv_sec'] *1000000+ $performance['ru_utime.tv_usec']+$performance['ru_stime.tv_sec'] *1000000+$performance['ru_stime.tv_usec']; var_dump($globalPerformStatics['cpu_time_end']-$globalPerformStatics['cpu_time_start']); ?> ———————————————————————————————— config/route.php <?php namespace Project\Order\Config; class Route { public static $routes = array( 'order/(.+)' => '$1', ); } ———————————————————————————————— helper/order.php <?php namespace Project\Order\Helper; class Order{ public static function selectSample($id) { $a = $id / 5.314; // 取反正切 0-5.314的变化区间 $b = 1000 / 1.520837931073; return intval((100 / $a) * $b); } } ———————————————————————————————— phputil <?php $loader->addPsr4('Project\Framework\\', FRAMEPATH . ''); //全局变量定义(暂时做法,限制性使用) $__uid = 0; $_startTime = ''; $_redisCount = 0; $_mysqlCount = 0; $_httpRpcCount = 0; $_thriftRpcCount = 0; try { $params = array('get' => $_GET, 'post' => $_POST); $routerConfigPath = $appNameSpace . '\Config\Route'; $routerConfig = array(); $errorPageConfig = false; if(class_exists($routerConfigPath)){ if(!empty($routerConfigPath::$routes) && is_array($routerConfigPath::$routes)){ $routerConfig = $routerConfigPath::$routes; } if(!empty($routerConfigPath::$showErrorPage)){ $errorPageConfig = $routerConfigPath::$showErrorPage; } } $_startTime = microtime(true); $router = new \Project\Framework\Base\Router($_SERVER['REQUEST_URI'], $routerConfig,$errorPageConfig); $router->setRoute(); $router->run($params); } catch (\InvalidArgumentException $ex) { $errNo = -1; $errMsg = strlen($ex->getMessage()) ? $ex->getMessage() : 'system error'; var_dump(array('errno' => $errNo, 'errmsg' => $errMsg)); } catch (\Exception $ex) { $errNo = $ex->getCode(); $errMsg = $ex->getMessage(); var_dump(array('errno' => $errNo, 'errmsg' => $errMsg)); }
-
ci
config/route.php CI多级目录支持需要自己开发,粗暴的把路由直接打到welcome.php $route['(.+)'] = 'welcome'; ———————————————————————————————— controller/Welcome.php <?php class Welcome extends CI_Controller { public function __construct() { parent::__construct(); $this->load->model('SampleModel'); } public function index() { echo "hello"; $orderId=$this->input->get('order_id'); $orderInfo = $this->SampleModel->selectSample($orderId); var_dump($orderInfo); return 1; } } ———————————————————————————————— model/SampleModel.php <?php class SampleModel extends CI_Model { public function selectSample($id) { $a = $id / 5.314; // 取反正切 0-5.314的变化区间 $b = 1000 / 1.520837931073; return intval((100 / $a) * $b); } public function insertSample($arrInfo) { return true; } }
php异步rpc
php协程
php为何不用多线程:
pthreads v3 is restricted to operating in CLI only: I have spent many years trying to explain that threads in a web server just don't make sense, after 1,111 commits to pthreads I have realised that, my advice is going unheeded.
So I'm promoting the advice to hard and fast fact: you can't use pthreads safely and sensibly anywhere but CLI.
Thanks for listening ;)
- yield原理:
http://note.youdao.com/notesh... - 用yield实现协程原理:
http://note.youdao.com/notesh...
curl_mutli
设为非阻塞的socket,调用libcurl的方法。也是select后执行,跟我们php协程处理方式差不多
curl_multi_init
curl_multi_add_handle
curl_multi_select
select有结果后curl_multi_perform // multi_runsingle.一个一个进行,状态流转,从任何一个状态都可以继续执行
当select结束后curl_multi_info_read
curl_multi_remove_handle,curl_multi_cleanup
swoole框架异步和corotine实现
swoole: https://wiki.swoole.com/wiki/...
协程原理:跳堆栈的原理
异步:客户端/mysql/redis/http等。这些只能在cli下调用。不能在fpm中, 异步就是设为非阻塞的socket, 然后设置回调。epoll。一个进程就行了。
自开发并发rpc
http协议封装libcurl.其他协议 状态机+epoll
workerman-thrift
需要分开提供发送和读取两个接口。对发送和读取两个步骤实现异步。先发送一批再读取,不是发完了等待接收再下一个。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 基于Google MVVM框架的baseMVVM框架
- Spring 框架是怎么出生的(二):重构提炼出框架
- Spring 框架是怎么出生的(二):重构提炼出框架
- Genesis框架从入门到精通(7): 框架的过滤器
- 如何打造自己的POC框架-Pocsuite3-框架篇
- 如何打造自己的PoC框架-Pocsuite3-框架篇
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Data Structures and Algorithm Analysis in Java
Mark A. Weiss / Pearson / 2006-3-3 / USD 143.00
As the speed and power of computers increases, so does the need for effective programming and algorithm analysis. By approaching these skills in tandem, Mark Allen Weiss teaches readers to develop wel......一起来看看 《Data Structures and Algorithm Analysis in Java》 这本书的介绍吧!