摘要:和服務關系最密切的進程是中的進程組,絕大部分業務處理都在該進程中進行。隨后觸發一個事件各組件通過該事件進行配置文件加載路由注冊。事件每個請求到來時僅僅會觸發事件。服務器生命周期和服務基本一致,詳情參考源碼剖析功能實現
作者:bromine
鏈接:https://www.jianshu.com/p/4c0...
來源:簡書
著作權歸作者所有,本文已獲得作者授權轉載,并對原文進行了重新的排版。
Swoft Github: https://github.com/swoft-clou...
Swoft源碼剖析系列目錄:https://segmentfault.com/a/11...前言
Swoft在PHPer圈中是一個門檻較高的Web框架,不僅僅由于框架本身帶來了很多新概念和前沿的設計,還在于Swoft是一個基于Swoole的框架。Swoole在PHPer圈內學習成本最高的工具沒有之一,雖然Swoft的出現降低了Swoole的使用成本,但如果你對Swoole本身了解不夠深入,仍然很難避免栽進種種"坑"中。
考慮到這個現狀,也為降低閱讀難度,后續幾個和Swoole聯系較為密切的機制,筆者會調整寫作思路,將文章的定位從 「幫助讀者深入理解Swoft」 調整為 「幫助讀者理解Swoft和Swoole」,敘述節奏也會放慢。
三種PHP應用的Web模型LNMP和LAMP是絕大多數PHPer最熟悉的基礎Web架構,這里以常見的LNMP作為例子描述一個常見 無Swoole應用的構件組成:Nginx充當Web Service, PHP-FPM維護一個進程池去運行Web項目。
對比更古老的CGI模型,PHP-FPM已經引入了進程常駐的概念,避免每次請求創建并銷毀進程的開銷以及拓展加載的開銷,但是每個請求仍然要執行PHP RINIT 與 RSHUTDOWN 之間的所有流程,包括重新加載一次框架源碼以及項目代碼,造成極大的性能浪費。
這種模型的優點是簡單成熟和穩定,一次運行隨后銷毀 帶來的開發便捷性是PHP能夠流行起來的原因之一。市面上絕大多數PHP項目使用的都是基于該種架構的變體。
LNMP-with-Swoole 是 LNMP的一種變體,其在LNMP的基礎上引入了Swoole組件。
和PHP-FPM一樣,Swoole有一套自己的進程管理機制。但由于代碼變得高度常駐和編程思維需要從同步到異步的轉變,所以Swoole和傳統的基于PHP-FPM的Web框架親和度很低,即使是適配升級過的老式Web框架,目前在Swoole上運行的表現往往并不好。
因此出現了這在這種折中方案,并沒有直接將原有PHP代碼運行在Swoole中,而是使用Swoole搭建了一個服務,系統通過接口與Swoole通信,從而為Web項目補充了異步處理的能力。我稱呼這種同時使用PHP-FPM和Swoole的系統為 半Swoole應用。因為接入簡單,所以是絕大多數現有項目優先考慮的Swoole接入方案。
LNMP-with-Swoole模型雖然引入了Swoole和異步處理能力,但是核心還是PHP-FPM,實際上還遠遠沒有發揮出Swoole的真正優勢。
Swoole-HTTP-Server和LNMP-with-Swoole相比有巨大的變化,這種模型中充當Web Server角色的構件不僅僅有Nginx,應用本身也包含了一個內建Web Server,不過由于Swoole Http Server不是專業的HTTP Server,對Http的處理不完善 ,因此仍然需要使用Nginx作為靜態資源服務器以及反代,Swoole HTTP Server僅僅處理PHP相關的HTTP流量。
一方面由于Swoole已經包含了WebServer,不再需要實現CGI或者Fast-CGI的通用協議去和Web Server通信,另一方面Swoole有自己的進程管理,因此PHP-FPM可以直接被去除了。對于PHP資源而言,在這種模型中,Swoole Http Server的地位相當于傳統模型中的Nginx和PHP-FPM之和。
一次加載常駐內存,不同的請求間基本上復用了onRequest以外的所有流程,使得每個請求的開銷大大降低;異步IO的特性使得這種模型吞吐量遠遠高于傳統的LNMP模型。另外相對于獨立的Swoole服務,內嵌在Web系統中的Swoole使用更加的直接方便,支持更好。
Swoft 和 Swoole 的關系是什么 ?Swoole是一個異步引擎,核心是為PHP提供異步IO執行的能力,同時提供一套異步編程可能會用到的工具集。
Swoole-HTTP-Server是Swoole的一個組件,是SwooleServer中的一種,提供了一個適合Swoole直接運行的HttpServer環境。
Swoft一個現代的Web框架,和Swoole親和性高,同時也是上面提到的Swoole-HTTP-Server模型的一個實踐。
Swoft管理著該Web模型中的Swoole,以及Swoole-HTTP-Server,對開發者屏蔽Swoole的種種復雜操作細節,并作為一個Web框架向開發者提供各種Web開發需要用到的路由,MVC,數據庫訪問等功能組件等。
Swoft 是如何使用 Swoole 的 ?最核心的就是HttpServer以及RpcServer
HTTP 服務器Swoft直接使用的是Swoole內建的SwooleHttpServer,它已經處理好所有HTTP層面的所有東西,我們只需要關注應用本身,我們來看一下HTTP服務幾個重要生命周期點。
Swoole 啟動前這個階段進行的行為有幾個特征
基礎bootstrap行為:如必須的常量定義,Composer加載器引入,配置讀取等;
需要生成被所有Worker/Task進程共享的程序全局期的對象,如SwooleLock,SwoftMemoryTable的創建;
啟動時,所有進程中合計只能執行一次的操作:如前置Process的啟動;
Bean容器基本初始化,以及項目啟動流程需要的coreBean的加載。
這塊涉及東西比較雜,為控制篇幅后續用多帶帶文章介紹。
和Http服務關系最密切的進程是Swoole中的Worker進程(組),絕大部分業務處理都在該進程中進行。
對于每個Swoole事件,Swoft都提供了對應的Swoole監聽器(對應@SwooleListener注解)作為事件機制的封裝。要理解Swoft的HttpServer是如何在Swoole下運行的我們重點需要關注下兩個在兩個Swoole事件swoole.workerStart和swoole.onRequest。
WorkerStart事件在TaskWorker/Worker進程啟動時發生,每個TaskWorker/Worker進程里都會執行一次。
這是個關鍵節點,因為swoole.workerStart回調之后新建的對象都是進程全局期的,使用的內存都屬于特定的Task/Worker進程,相互獨立。也只有在這個階段或以后初始化的部分才是可以被熱重載的。
事件底層關鍵代碼如下:
// SwoftBootstrapServerServerTrait.php /** * @param bool $isWorker * @throws InvalidArgumentException * @throws ReflectionException */ protected function reloadBean(bool $isWorker) { BeanFactory::reload(); $initApplicationContext = new InitApplicationContext(); $initApplicationContext->init(); if($isWorker && $this->workerLock->trylock() && env("AUTO_REGISTER", false)){ App::trigger(AppEvent::WORKER_START); } }
這里做的事情有3點
初始化Bean容器:
上文中的BeanFactory::reload();就是Swoft的Bean容器初始化入口,注解的掃描也是在此處進行(實際上這個說法并不準確,Bean容器真正的初始化階段在Swoole Server啟動前的BootStrap階段就已經進行了,只不過那時進行的是少部分初始化,相對swoole.workerStart中的初始化的Bean數量,比重很?。T?b>workerStart中初始化Bean容器是Swoft可以熱更新代碼的基礎。
初始化的應用上下文
initApplicationContext->init()會注冊Swoft事件監聽器(對應@Listener),方便用戶處理Swoft應用本身的各種鉤子。隨后觸發一個swoft.applicationLoader事件,各組件通過該事件進行配置文件加載,HTTP/RPC路由注冊。
服務注冊
具體內容會在服務治理章節講述。
每個HTTP請求到來時僅僅會觸發swoole.onRequest事件。
框架代碼本身都是由大量進程全局期和少量程序全局期的對象構成,而onReceive中創建的對象譬如$request和$response都是請求期的,隨著HTTP請求的結束而回收。
事件底層關鍵代碼如下:
/** * @param array ...$params * @return PsrHttpMessageResponseInterface * @throws InvalidArgumentException */ public function dispatch(...$params): ResponseInterface { /** * @var RequestInterface $request * @var ResponseInterface $response */ list($request, $response) = $params; try { // before dispatcher $this->beforeDispatch($request, $response); // request middlewares $middlewares = $this->requestMiddleware(); $request = RequestContext::getRequest(); $requestHandler = new RequestHandler($middlewares, $this->handlerAdapter); $response = $requestHandler->handle($request); } catch (Throwable $throwable) { /* @var ErrorHandler $errorHandler */ $errorHandler = App::getBean(ErrorHandler::class); $response = $errorHandler->handle($throwable); } $this->afterDispatch($response); return $response; }
beforeDispatch($request, $response):
設置請求上下文,并觸發一個swoft.beforeRequest事件。
RequestHandler->handle($request):
執行各個 中間件 和請求對應的 Action,具體處理可以參考RPC章節,原理基本相同。
$afterDispatch($response):
整理HTTP響應報文發送客戶端并觸發swoft.resourceRelease(詳情在連接池一文中提及)事件和swoft.afterRequest事件
總的來說,縱觀這幾個生命周期點你需要搞清楚幾件事:
Swoole的Worker進程是你絕大多數HTTP服務代碼的運行環境。
一部分初始化和加載操作在Swoole的Server啟動前完成,一部分在swoole.workerStart事件回調中完成,前者無法熱重載但可能被多個進程共享。
初始化代碼只會在系統啟動和Worker/Task進程啟動時執行一次, 不像PHP-FPM每次請求都會執行一次,框架對象也不像PHP-FPM會隨請求返回而銷毀。
每次請求都會觸發一次swoole.onRequest事件,里面就是我們的請求處理代碼真正運行的地方,只有這事件內產生的對象才會在請求結束時被回收。
RPC服務器生命周期和HTTP服務基本一致,詳情參考《Swoft源碼剖析-RPC功能實現》
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/29027.html
摘要:作者鏈接來源簡書著作權歸作者所有,本文已獲得作者授權轉載,并對原文進行了重新的排版。同時順手整理個人對源碼的相關理解,希望能夠稍微填補學習領域的空白。系列文章只會節選關鍵代碼輔以思路講解,請自行配合源碼閱讀。 作者:bromine鏈接:https://www.jianshu.com/p/2f6...來源:簡書著作權歸作者所有,本文已獲得作者授權轉載,并對原文進行了重新的排版。Swoft...
摘要:作為定時任務的執行者,通過每喚醒自身一次,然后把執行表遍歷一次,挑選當下需要執行的任務,通過投遞出去并更新該任務執行表中的狀態。 作者:bromine鏈接:https://www.jianshu.com/p/b44...來源:簡書著作權歸作者所有,本文已獲得作者授權轉載,并對原文進行了重新的排版。Swoft Github: https://github.com/swoft-clou.....
摘要:值得一提的是目前的服務即服務,暫沒有其他的服務功能,所以基本上相關的配置指代的就是。會將請求傳遞給各個中間件,最終最終傳遞給處理。源碼剖析系列目錄 作者:bromine鏈接:https://www.jianshu.com/p/411...來源:簡書著作權歸作者所有,本文已獲得作者授權轉載,并對原文進行了重新的排版。Swoft Github: https://github.com/swo...
摘要:作者鏈接來源簡書著作權歸作者所有,本文已獲得作者授權轉載,并對原文進行了重新的排版。文件重載管理進程注冊了一個名為的該進程會在系統引導的最后一個階段,即啟動前啟動。 作者:bromine鏈接:https://www.jianshu.com/p/e63...來源:簡書著作權歸作者所有,本文已獲得作者授權轉載,并對原文進行了重新的排版。Swoft Github: https://githu...
摘要:在中的應用官網源碼解讀號外號外歡迎大家我們開發組定了一個就線下聚一次的小目標上一篇源碼解讀反響還不錯不少同學推薦再加一篇講解一下中使用到的功能幫助大家開啟的實戰之旅服務器開發涉及到的相關技術領域的知識非常多不日積月累打好基礎是很難真正 date: 2017-12-14 21:34:51title: swoole 在 swoft 中的應用 swoft 官網: https://www.sw...
閱讀 841·2021-11-16 11:56
閱讀 1653·2021-11-16 11:45
閱讀 3109·2021-10-08 10:13
閱讀 4094·2021-09-22 15:27
閱讀 726·2019-08-30 11:03
閱讀 642·2019-08-30 10:56
閱讀 945·2019-08-29 15:18
閱讀 1737·2019-08-29 14:05