協程能夠理解爲純用戶態的線程,其經過協做而不是搶佔來進行切換,相對於進程或者線程,協程全部的操做均可以在用戶態完成,建立和切換的消耗更低,Swoole 能夠爲每個請求建立對應的協程,根據 IO 的狀態來合理的調度協程。php
在 Swoole 4.x 中,協程(Coroutine)取代了異步回調,成爲 Swoole 官方推薦的編程方式。Swoole 協程解決了異步回調編程困難的問題,使用協程能夠以傳統同步編程的方法編寫代碼,底層自動切換爲異步 IO,既保證了編程的簡單性,又可藉助異步 IO,提高系統的併發能力。html
開啓swoole的http服務並設置提供給url訪問頁面的文件的根目錄,nginx
代碼以下。這樣在瀏覽器只能訪問…static下面的文件,而沒法訪問其餘目錄下的文件。laravel
http.serversql
<?php //開啓http server $http = new swoole_http_server("0.0.0.0", 9905); $http->set( [ 'enable_static_handler' => true, 'document_root' => "/usr/local/openresty/nginx/html/swoole/LiveRadio/public/static", 'worker_num' => 5 ] ); $http->on('request', function($request, $response) { $response->end("sss". json_encode($request->get)); }); $http->start();
swoole有一個事件回調函數onWorkStart,此事件在Worker進程/Task進程啓動時發生。這裏建立的對象能夠在進程生命週期內使用。thinkphp
原型:shell
function onWorkerStart(swoole_server $server, int workerid);編程
(1)onWorkerStart/onStart是併發執行的,沒有前後順序;json
(2)能夠經過server->taskworker屬性來判斷當前是Worker進程仍是Task進程;數組
(3)設置了worker_num和task_worker_num超過1時,每一個進程都會觸發一次onWorkerStart事件,可經過判斷$worker_id區分不一樣的工做進程;
(4)由 worker 進程向 task 進程發送任務,task 進程處理徹底部任務以後經過onFinish回調函數通知worker 進程。
例如,咱們在後臺操做向十萬個用戶羣發通知郵件,操做完成後操做的狀態顯示爲發送中,這時咱們能夠繼續其餘操做。等郵件羣發完畢後,操做的狀態自動改成已發送。
在onWorkerStart中加載框架的核心文件後:
(1)不用每次請求都加載框架核心文件,提升性能;
(2)能夠在後續的回調事件中繼續使用框架的核心文件或者類庫。
項目目錄下的public文件夾下的index.php是入口文件,源碼以下:
<?php // [ 應用入口文件 ] // 定義應用目錄 define('APP_PATH', __DIR__ . '/../application/'); // 加載框架引導文件 require __DIR__ . '/../thinkphp/start.php';
這個文件加載了…thinkphp/start.php’,start.php加載了一個核心文件base.php,因此咱們須要把base.php文件加載到onWorkStart回調函數裏面,每一個worker進程都會觸發一次onWorkerStart事件,所以ThinkPHP框架內的入口文件等內容就能加載入咱們的項目。
修改http.server以下:
<?php //開啓http server $http = new swoole_http_server("0.0.0.0", 9906); $http->set( [ 'enable_static_handler' => true, 'document_root' => "/usr/local/openresty/nginx/html/swoole/LiveRadio/public/static", 'worker_num' => 5 //設置worker進程數 ] ); $http->on('WorkerStart', function (swoole_server $server, $worker_id){ //定義應用目錄 define('APP_PATH', __DIR__ . '/../application/'); // 加載基礎文件 //這裏不直接加載start.php的緣由是start.php中的代碼會直接執行,也就是application\index\controller\Index.php文件(框架的默認首頁) /* * Container::get('app', [defined('APP_PATH') ? APP_PATH : '']) ->run() ->send(); */ require __DIR__ . '/../thinkphp/base.php'; }); $http->on('request', function($request, $response){ //適配 /* *因爲swoole http提供的API和原生php代碼是有所不一樣的,好比原生php中獲取get參數爲直接從全局數組_GET中獲取,而swoole http中是經過$request->get()的方式獲取,所以要轉換成原生的 * */ $_SERVER = []; if(isset($request->server)){ foreach($request->header as $k => $v){ $_SERVER[strtoupper($k)] = $v; } } $_GET = []; if(isset($request->get)){ foreach($request->get as $k => $v){ $_GET[$k] = $v; } } $_POST = []; if(isset($request->post)){ foreach($request->post as $k => $v){ $_POST[$k] = $v; } } //..其他參數用到的繼續日後寫 ob_start(); // 執行應用並響應 try { think\Container::get('app', [APP_PATH]) ->run() ->send(); }catch (\Exception $e){ //todo } $res = ob_get_contents(); ob_end_clean(); $response->end($res); }); $http->start();
此時,用瀏覽器訪問 http://ip:port/?s=index/index/index 能夠看到ThinkPHP的默認首頁,可是發現訪問不到http://ip:port/?s=index/index/hello?name=world頁面。
能夠打印出路由看看。在項目目錄\thinkphp\library\think\App.php文件中的routeCheck接口,打印path變量,能夠看到url改變後path變量並無改變。這是由於onWorkerStart進程加載框架的時候就複用了類成員變量。
/** * URL路由檢測(根據PATH_INFO) * @access public * @return Dispatch */ public function routeCheck() { $path = $this->request->path(); echo "path:".$path."<br/>"; // var_dump($this->request); $depr = $this->config('app.pathinfo_depr'); // 路由檢測 $files = scandir($this->routePath); foreach ($files as $file) { if (strpos($file, '.php')) { $filename = $this->routePath . DIRECTORY_SEPARATOR . $file; // 導入路由配置 $rules = include $filename; if (is_array($rules)) { $this->route->import($rules); } } } // 是否強制路由模式 $must = !is_null($this->routeMust) ? $this->routeMust : $this->config('app.url_route_must'); // 路由檢測 返回一個Dispatch對象 return $this->route->check($path, $depr, $must, $this->config('app.route_complete_match')); }
修改:
進入 項目目錄\thinkphp\library\think\Request.php中
(1)找到function path() { },註銷判斷,再也不復用類成員變量 $ this->path。
(2)找到function pathinfo() { },註銷判斷,再也不復用類成員變量$this->pathinfo。
(3)使其支持pathinfo路由,在function pathinfo() { }中添加代碼
if (isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'] != '/') { return ltrim($_SERVER['PATH_INFO'], '/'); }
此時用瀏覽器訪問:
好了各位,以上就是這篇文章的所有內容了,能看到這裏的人呀,都是人才。以前說過,PHP方面的技術點不少,也是由於太多了,實在是寫不過來,寫過來了你們也不會看的太多,因此我這裏把它整理成了PDF和文檔,若是有須要的能夠
更多學習內容能夠訪問【對標大廠】精品PHP架構師教程目錄大全,只要你能看完保證薪資上升一個臺階(持續更新)
以上內容但願幫助到你們,不少PHPer在進階的時候總會遇到一些問題和瓶頸,業務代碼寫多了沒有方向感,不知道該從那裏入手去提高,對此我整理了一些資料,包括但不限於:分佈式架構、高可擴展、高性能、高併發、服務器性能調優、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql優化、shell腳本、Docker、微服務、Nginx等多個知識點高級進階乾貨須要的能夠免費分享給你們,須要的能夠加入個人 PHP技術交流羣