您好,登錄后才能下訂單哦!
小編給大家分享一下ThinkPHP框架如何使用fastcgi_finish_request和trait,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
當(dāng)執(zhí)行完控制器中的方法響應(yīng)數(shù)據(jù)給App類的run方法,直到這里就已經(jīng)執(zhí)行完了。
是不是有點懵這里的數(shù)據(jù)最終會返回哪里呢!
之前寫過的框架執(zhí)行流程、路由、控制器實例化都是從這里開始進(jìn)入的。
所以當(dāng)run方法執(zhí)行完成之后,就會把對應(yīng)的結(jié)果給返回到這里。
這一部分的代碼Container::get('app')
應(yīng)該都知道了是返回一個App類的實例。
然后通過App類去執(zhí)行run方法,才會有之前講過的一切。
下圖是咔咔從半中腰做的一個思維導(dǎo)圖,前面的沒有,后邊的所有知識點都會寫在這個思維導(dǎo)圖里。
執(zhí)行完run方法就會去執(zhí)行Container::get('app')->run()->send()
send這個方法,有多少人會認(rèn)為在App類里邊執(zhí)行send方法。
其實不是的,回想一下之前執(zhí)行控制器方法然后返回的響應(yīng)結(jié)果是什么?
如果你不是很粗略的看都會記得是Response的一個對象實例。
所以說send方法會去response類里邊去執(zhí)行。
先不看其它的,先看這行代碼$this->app['hook']
,現(xiàn)在知道是執(zhí)行的那里嗎?
這種形式就是通過訪問數(shù)組形式去訪問對象的屬性,也就是之前解析的ArrayAccess這個類。當(dāng)訪問的屬性不存在時會去執(zhí)行offsetGet,然后執(zhí)行魔術(shù)方法__get,最終通過make方法返回實例,這一切的操作都是在容器中。
對這行代碼具體是監(jiān)聽的什么就不去做解析了。
接著需要看處理輸出數(shù)據(jù)的這行代碼$data = $this->getContent();
這個方法做的事情就是將傳過來的數(shù)據(jù)賦值給本類的content屬性。
其實在獲取輸出數(shù)據(jù)這個方法中,請看咔咔圈出來的第一個地方感覺是很沒有必要。
可以看到根本對數(shù)據(jù)就沒有任何的處理,只是簡單的返回了,所以說框架有好的地方也有不好的地方,只有你去閱讀了才會知道,否則你會對你經(jīng)常使用的工具一無所知。
在接著就是Trace調(diào)試注入,就是通過配置文件配置的,通過調(diào)用debug類實現(xiàn)的,這里就不詳解了。
然后就是緩存判斷,緩存會在后文中單獨拎出來講,所以也是過。
在接下來就對響應(yīng)頭的設(shè)置了,檢測 HTTP 頭是否已經(jīng)發(fā)送,這塊的東西就很重要了,也是平時接觸不多的知識點了。
最后一步,來了來了,它來了,它帶著echo來了,執(zhí)行了一個方法$this->sendData($data);
給人一種媳婦熬成娘的感覺,終于來到的終點站,一個echo輸出了咔咔幾十天的心酸啊!
為了到達(dá)這個echo咔咔是經(jīng)歷九九八十一難?。?zhàn)斗還未停止,同志仍需努力?。?/p>
那么到這里關(guān)于框架執(zhí)行然后到應(yīng)用初始化,在到路由檢測、控制器的實例化、然后返回response實例,在通過入口文件執(zhí)行send方法。
最后將數(shù)據(jù)輸出到終端,也就是一個echo的事情。
雖然這里的戰(zhàn)斗結(jié)束了,但是在下面還有一個非常重要的知識點,咔咔將重新提一節(jié)來進(jìn)行說明。
在上一節(jié)中通過Container::get('app')->run()->send();
在response類中執(zhí)行了send方法,輸出了數(shù)據(jù)。
但是在輸出數(shù)據(jù)之后還執(zhí)行了一個方法fastcgi_finish_request();
,給的注釋是提高頁面響應(yīng),接下來好好來扒一扒其中的奧秘。
在PHP官網(wǎng)中看到這樣一段話
The script will still occupy a FPM process after fastcgi_finish_request(). So using it excessively for long running tasks may occupy all your FPM threads up to pm.max_children. This will lead to gateway errors on the webserver.
在fastcgi_finish_request()之后,腳本仍將占用FPM進(jìn)程。 因此,對于長時間運行的任務(wù)過度使用它可能會占用您的所有FPM線程,直到pm.max_children。 這將導(dǎo)致Web服務(wù)器上的網(wǎng)關(guān)錯誤。
所以說在沒有徹底的了解這個方法之前不要輕易的在自己的項目中使用這個方法。
接下來咔咔將使用一個案例來演示這個方法的使用,僅僅只是演示使用,如果需要使用到項目中請仔細(xì)閱讀文檔應(yīng)該注意的問題。
案例演示
公司有一個業(yè)務(wù)需要發(fā)送通知給用戶,但是由于發(fā)送時間太久,非常費時間,有可能需要好幾十秒的時間,更嚴(yán)重的會直接導(dǎo)致瀏覽器連接超時。
在一個問題就是用戶體驗的問題,用戶等待時間過程,體驗當(dāng)然不好。
為了解決以上倆個問題,今天談?wù)摰?code>fastcgi_finish_request就派上了用場。
理解
對這個函數(shù)的理解其實就是發(fā)送響應(yīng)給瀏覽器,用戶等待時間大大縮短,但是PHP進(jìn)程還是在運行的。
這樣就達(dá)到了來個目的,就類似于我們經(jīng)常說的異步執(zhí)行。
直觀的來說就是發(fā)送郵件有可能需要10秒,但是用戶是沒有感知的,用戶點擊發(fā)送郵件之后直接就返回發(fā)送成功,瀏覽器響應(yīng)結(jié)束,用戶做其它事情,后臺進(jìn)程繼續(xù)執(zhí)行發(fā)送郵件的任務(wù)。
案例
具體代碼
<?php
/**
* 設(shè)置超時時間,變成不限制
*
*/
set_time_limit(0);
/**
* 本函數(shù)模擬非常耗時的任務(wù),執(zhí)行完畢需要5秒的時間
*/
function writeFile()
{
$path = 'D:/phpstudy_pro/WWW/kaka.txt';
file_put_contents($path,'程序運行開始' . PHP_EOL,FILE_APPEND);
for($i =0;$i < 5;$i++) {
file_put_contents($path,time() . PHP_EOL,FILE_APPEND);
sleep(1);
}
file_put_contents($path,'程序運行結(jié)束' . PHP_EOL,FILE_APPEND);
}
/**
* 輸出文字標(biāo)記,任務(wù)開始
*/
echo('任務(wù)開始');
/**
* 后臺執(zhí)行非常耗時的任務(wù)
*/
register_shutdown_function(writeFile);
/**
* 立即發(fā)送請求
*/
fastcgi_finish_request();
以上測試全部使用linux系統(tǒng)進(jìn)行測試哈,否則你看不到直觀的效果。
經(jīng)過上面的演示,響應(yīng)非??欤瑸g覽器響應(yīng)結(jié)束后,后臺程序依然進(jìn)行執(zhí)行每秒執(zhí)行一個時間戳。
以上就是對fastcgi_finish_request
方法的簡單介紹,如果你也感興趣可以進(jìn)行簡單的嘗試一下,有助于更好的去理解其中的小秘密。
應(yīng)該在倆年前咔咔就對這個特性進(jìn)行過一次解析,trait
就是常說的超類。
這個特性是在PHP5.4才加入的,這個特性不是經(jīng)常使用的接口更不是類。
這個特性是為了解決PHP的一大弱點只能單繼承的缺點,但是也不能叫多繼承,嚴(yán)謹(jǐn)一點的就是類似多繼承的功能而已。
接下來給大家演示一個案例。
創(chuàng)建test文件一,并且返回對應(yīng)類名。
創(chuàng)建test1文件,并且返回對應(yīng)類名
創(chuàng)建控制器文件用來輸出信息。
然后在控制器中引入對應(yīng)的超類文件,這里需要注意的是圈住的第一個框,這個框就是直接引入超類test文件。
然后可以直接進(jìn)行訪問,看會返回什么。
通過上圖訪問結(jié)果結(jié)果可以看得到返回的是Test超類文件的方法,但是此控制器同樣也基礎(chǔ)了Controller控制器,這也就是在文章一開頭就說的超類就是實現(xiàn)了一種多繼承的功能而已。
但是這里會存在一個問題,請看下圖報錯信息。
上圖的報錯信息是因為在控制器中使用了倆個超類導(dǎo)致的,也就是下圖的使用方式。
那么如何解決這種報錯信息呢!接下來跟這咔咔的節(jié)奏一起來。
解決報錯信息
在解決之前問題之前得先清楚這個問題是由于什么引起的。
出現(xiàn)這個錯誤的原因是引用的兩個trait里面有同名的hello函數(shù),出現(xiàn)了沖突。
但是在日常開發(fā)中這種情況都是可以避免的,因為手動改方法名還是很方便的,但是這里咔咔教大家如何解決這種問題。
一是用其中一個trait里的hello方法覆蓋另外一個trait的同名方法,因為兩個方法內(nèi)容是一致的,所以我這里直接選擇insteadof覆蓋;
二是給他們用as起別名,這樣就不會有沖突了。as關(guān)鍵詞還有另外一個用途,那就是修改方法的訪問控制。
經(jīng)過上圖的改動之后,再一次的進(jìn)行訪問,看一下返回結(jié)果。
那么這個時候就會有伙伴有疑問了,就是案例打印結(jié)果一直是Test類的方法,Test1類的方法一直沒有進(jìn)行打印。
那是如何進(jìn)行訪問的呢!來接著看一下。
從上圖可以看到將訪問方法改為了別名控制訪問,接著來看一下訪問結(jié)果。
從上圖中可以可以看到返回結(jié)果就是超類Test1類的返回結(jié)果。
那么關(guān)于as這個的使用就需要大家在去搜索一下使用方式,有時候注意一下細(xì)節(jié)就可以學(xué)到很多知識點。
直到這里關(guān)于控制器的源碼解析就到這了,咔咔通過源碼給大家分析控制器的如如何進(jìn)行實例化的。
也再一次的進(jìn)行了對ArrayAccess和魔術(shù)方法的調(diào)用關(guān)系,一定要有自己的思考去想問題。
在就是對訪問控制器后是如何進(jìn)行響應(yīng)數(shù)據(jù)的,等等。
也在源碼中學(xué)到了關(guān)于fastcgi_finish_request方法巧用,但是在使用這個函數(shù)一定要注意關(guān)于咔咔提到的倆個注意點。
最后就是對超類的一個簡單案例描述。
看完了這篇文章,相信你對“ThinkPHP框架如何使用fastcgi_finish_request和trait”有了一定的了解,如果想了解更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。