php框架的功能通用的路由,autoload。服務端mysql封裝,日誌組件。前端的頁面渲染(smarty封裝個)。在工做時據說別的部門換框架性能提高,因此調研了下常見的框架,包含ci,laravel,yii,yaf,會介紹下功能,另外給出號稱最快框架yaf和經常使用yii和裸寫框架的性能差。另外想實現rpc併發,http通常用過multi_curl能夠,公司用的thrift沒有實現併發,因此研究了下php協程,curl_multi,swoole異步,rpc中併發實現,corotine等。php
laravel https://laravel-china.org/doc...
路由
中間件(前置後置)
配置區分環境,本地和線上密碼不放其中
數據庫 建立表,編輯,刪除,遷移,回滾,軟刪除和恢復(標記刪除位)。ORM鏈式操做
依賴注入,依賴自動發現。html
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監聽
任務調度 只是cronmysql
yii https://www.yiichina.com/doc/...
功能全面讀介於ci和laravel之間,前端支持功能豐富。組件和行爲是它的特點
行爲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組件就能夠使用行爲了。
直觀感覺下
git
裸寫在CPU佔用方面和YAF相近,略高,在內存方面更節省。在吞吐量方面和YAF相近,略好。
CI框架會比YAF在CPU方面多耗費10%。吞吐量要差75%github
yafweb
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; } }
裸寫redis
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)); }
cisql
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爲什麼不用多線程:
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 ;)
設爲非阻塞的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:https://wiki.swoole.com/wiki/...
協程原理:跳堆棧的原理
異步:客戶端/mysql/redis/http等。這些只能在cli下調用。不能在fpm中, 異步就是設爲非阻塞的socket, 而後設置回調。epoll。一個進程就好了。
http協議封裝libcurl.其餘協議 狀態機+epoll
須要分開提供發送和讀取兩個接口。對發送和讀取兩個步驟實現異步。先發送一批再讀取,不是發完了等待接收再下一個。