摘要:如下圖目錄結(jié)構(gòu)主要針對(duì)的是非常駐內(nèi)存方式運(yùn)行,為了兼容,雖然做了很多優(yōu)化,但是仍然無法像,等一些針對(duì)開發(fā)的框架一樣。在非常住內(nèi)存框架中,為了方便會(huì)有一些寫法導(dǎo)致在常駐內(nèi)存方式下不容易被釋放內(nèi)存,小則內(nèi)存泄漏,大則數(shù)據(jù)錯(cuò)亂。
前言
ThinkPHP即將迎來最新版本6.0,針對(duì)目前越來越流行Swoole,thinkphp也推出了最新的擴(kuò)展think-swoole 3.0架構(gòu)分析
tp-swoole3.0不同于2.0版本,采用了全新的架構(gòu)。(如下圖目錄結(jié)構(gòu))
tp主要針對(duì)的是非常駐內(nèi)存方式運(yùn)行,為了兼容swoole,雖然做了很多優(yōu)化,但是仍然無法像swoft,sd等一些針對(duì)swoole開發(fā)的框架一樣。這里所說的不同,不是指tp不好,而是因?yàn)閮煞N模式都要兼容,不得不做出一些取舍。
請(qǐng)求分析該框架的運(yùn)行機(jī)制,其實(shí)主要分析swoole的OnRequest函數(shù)即可,路由分發(fā),數(shù)據(jù)處理等都是在函數(shù)處進(jìn)行處理的。
Swoole.php
public function onRequest($req, $res) { $this->app->event->trigger("swoole.request"); $this->resetOnRequest(); /** @var Sandbox $sandbox */ $sandbox = $this->app->make(Sandbox::class); $request = $this->prepareRequest($req); try { $sandbox->setRequest($request); $sandbox->init(); $response = $sandbox->run($request); $this->sendResponse($sandbox, $response, $res); } catch (Throwable $e) { try { $exceptionResponse = $this->app ->make(Handle::class) ->render($request, $e); $this->sendResponse($sandbox, $exceptionResponse, $res); } catch (Throwable $e) { $this->logServerError($e); } } finally { $sandbox->clear(); } }
函數(shù)初始處,觸發(fā)了一個(gè)request事件,這里方便用戶自定義處理請(qǐng)求,進(jìn)行一些定制化處理
$this->app->event->trigger("swoole.request");
重置請(qǐng)求,當(dāng)是Websocket的時(shí)候,重置該類,具體為什么,下次我們分析Websocket的時(shí)候在進(jìn)行解釋
$this->resetOnRequest(); protected function resetOnRequest() { // Reset websocket data if ($this->isServerWebsocket) { $this->app->make(Websocket::class)->reset(true); } }
接下來通過容器獲取沙盒,這里也是關(guān)鍵之處。在非常住內(nèi)存框架中,為了方便會(huì)有一些寫法導(dǎo)致在常駐內(nèi)存方式下不容易被釋放內(nèi)存,小則內(nèi)存泄漏,大則數(shù)據(jù)錯(cuò)亂。而沙盒可以很好的解決這個(gè)問題。(文章最后會(huì)介紹一個(gè)造成內(nèi)存泄漏和數(shù)據(jù)錯(cuò)亂的案例)
$sandbox = $this->app->make(Sandbox::class);
請(qǐng)求進(jìn)行預(yù)處理,這里進(jìn)行的是request的轉(zhuǎn)換,從swoole的request轉(zhuǎn)換到tp的request
$request = $this->prepareRequest($req); $header = $req->header ?: []; $server = $req->server ?: []; if (isset($header["x-requested-with"])) { $server["HTTP_X_REQUESTED_WITH"] = $header["x-requested-with"]; } if (isset($header["referer"])) { $server["http_referer"] = $header["referer"]; } if (isset($header["host"])) { $server["http_host"] = $header["host"]; } // 重新實(shí)例化請(qǐng)求對(duì)象 處理swoole請(qǐng)求數(shù)據(jù) /** @var hinkRequest $request */ $request = $this->app->make("request", [], true); return $request->withHeader($header) ->withServer($server) ->withGet($req->get ?: []) ->withPost($req->post ?: []) ->withCookie($req->cookie ?: []) ->withInput($req->rawContent()) ->withFiles($req->files ?: []) ->setBaseUrl($req->server["request_uri"]) ->setUrl($req->server["request_uri"] . (!empty($req->server["query_string"]) ? "&" . $req->server["query_string"] : "")) ->setPathinfo(ltrim($req->server["path_info"], "/"));
對(duì)沙盒進(jìn)行設(shè)置,并初始化沙盒
$sandbox->setRequest($request); $sandbox->init();
啟動(dòng)沙盒
$response = $sandbox->run($request);
如果發(fā)生異常,則將異常信息處理并發(fā)送
try { $exceptionResponse = $this->app ->make(Handle::class) ->render($request, $e); $this->sendResponse($sandbox, $exceptionResponse, $res); } catch (Throwable $e) { $this->logServerError($e); }
最終需要將沙盒信息清除
$sandbox->clear();
以上是tp-swoole對(duì)HTTP的處理流程,下文會(huì)詳細(xì)介紹沙盒的運(yùn)行機(jī)制
番外篇 常駐內(nèi)存易忽略的問題class A{ private static $intance=null; public static function getInstance(){ if (!empty(self::$intance)){ return self::$intance; } self::$intance = new static(); return self::$intance; } public static function clear(){ self::$intance=null; } public function echo(){ echo "echo"; } } $b = A::getInstance(); A::clear(); print_r($b->echo());
以上代碼會(huì)報(bào)錯(cuò)嗎?
不會(huì)。仍然會(huì)輸出echo
下面在做另外一個(gè)實(shí)驗(yàn)
class A { private static $intance = null; private $echo = "echo"; public static function getInstance() { if (!empty(self::$intance)) { return self::$intance; } self::$intance = new static(); return self::$intance; } public static function clear() { self::$intance = null; } public function echo() { echo $this->echo; } public function setEcho($echo) { $this->echo = $echo; } } $b = A::getInstance(); $a = A::getInstance(); $a->setEcho("b"); print_r($b->echo()); A::clear(); print_r($b->echo()); $a->setEcho("a"); print_r($b->echo());
以上代碼會(huì)輸出什么?
答案是:bba。那么為什么不僅沒有報(bào)錯(cuò),還輸出這樣的答案
PHP的變量對(duì)象引入是地址引用,當(dāng)$a和$b被賦值時(shí),他們所存的內(nèi)容都是一樣的,且只有一份都是self::$intance位置所存放的內(nèi)容。修改$a或$b都會(huì)修改self::$intance,那么為何當(dāng)self::$intance為清除后,$a和$b仍然正常?基于PHP寫時(shí)復(fù)制,當(dāng)self::$intance被清空,就會(huì)復(fù)制出來一份給$a和$b來使用。
當(dāng)我們?cè)诜浅W?nèi)存方式開發(fā)時(shí),這些都不需要注意,因?yàn)槊看握?qǐng)求都相當(dāng)于一個(gè)多帶帶的線程,初始化所有數(shù)據(jù),最后在將所有數(shù)據(jù)銷毀,且所有數(shù)據(jù)都是按照順序執(zhí)行的。長(zhǎng)住內(nèi)存方式,就需要注意這些問題,不然會(huì)出現(xiàn)類似線程安全的問題。至于為何會(huì)出現(xiàn)這樣的問題,下文再敘。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/31641.html
摘要:由于是基于容器創(chuàng)建和銷毀資源的,那么各個(gè)容器之間是相對(duì)隔離的。也就是說每次請(qǐng)求都會(huì)創(chuàng)建一個(gè)新的環(huán)境用于執(zhí)行和解析,由于容器的隔離性,每個(gè)請(qǐng)求都不會(huì)和其他請(qǐng)求進(jìn)行干擾。因?yàn)橹挥挟?dāng)前協(xié)程才可以讀取到該數(shù)據(jù)。 前言 ThinkPHP即將迎來最新版本6.0,針對(duì)目前越來越流行Swoole,thinkphp也推出了最新的擴(kuò)展think-swoole 3.0 沙盒 本文主要介紹在ThinkPHP-...
摘要:前言即將迎來最新版本,針對(duì)目前越來越流行,也推出了最新的擴(kuò)展安裝由于目前沒有穩(wěn)定版本,所以只能安裝開發(fā)板接下來安裝,目前最新的穩(wěn)定版本是配置安裝結(jié)束可以根據(jù)自己的需求對(duì)配置信息進(jìn)行修改。 前言 ThinkPHP即將迎來最新版本6.0,針對(duì)目前越來越流行Swoole,thinkphp也推出了最新的擴(kuò)展think-swoole 3.0 安裝 由于目前thinkphp 6.0沒有穩(wěn)定版本,所...
摘要:前言即將迎來最新版本,針對(duì)目前越來越流行,也推出了最新的擴(kuò)展。介紹即將推出的,已經(jīng)適配并推出,并且默認(rèn)適配了。和版本在使用方法上面有些許不同。其中的第一個(gè)參數(shù)和的第一個(gè)參數(shù)一致,作為事件名稱。 前言 ThinkPHP即將迎來最新版本6.0,針對(duì)目前越來越流行Swoole,thinkphp也推出了最新的擴(kuò)展think-swoole 3.0。 介紹 即將推出的tp6.0,已經(jīng)適配swool...
摘要:安裝框架安裝如果已經(jīng)安裝了可以跳過本步驟,但是請(qǐng)確定通過命令來確保已經(jīng)使用了最新版本的使用以下命令可以直接通過官網(wǎng)下載并自動(dòng)安裝到目錄下如果以上安裝過程極慢的話,可以嘗試用以下方式通過國(guó)內(nèi)鏡像來安裝。 《當(dāng) Swoole 遇上 ThinkPHP5》:Hello,World! 本文假設(shè)你已經(jīng)有了 Linux 操作系統(tǒng)的 PHP 環(huán)境,強(qiáng)烈推薦使用 Vagrant 來搭建開發(fā)環(huán)境 安裝 ...
摘要:文章目錄一線性模型二繪圖工具三作業(yè)一線性模型不要小看簡(jiǎn)單線性模型哈哈,雖然這講我們還沒正式用到,但是用到的前向傳播損失函數(shù)兩種繪圖等方法在后面是很常用的。 文章目...
閱讀 3486·2021-11-12 10:36
閱讀 2857·2021-09-22 15:35
閱讀 2807·2021-09-04 16:41
閱讀 1164·2019-08-30 15:55
閱讀 3574·2019-08-29 18:43
閱讀 2070·2019-08-23 18:24
閱讀 1412·2019-08-23 18:10
閱讀 1921·2019-08-23 11:31