SWOOLE分佈式框架之IOC容器構建

一、swoole的運行模式

Swoole高效跟傳統的web開發有什麼區別,除了傳統的LAMP/LNMP同步開發模式,swoole的異步開發模式是怎麼樣的。

1.1、傳統web開發模式

PHP web開發採用的方式是LAMP/LNMP架構,即Linux、Nginx,Mysql和PHP。這裏以nginx來舉例,大致結構爲:

attachments-2021-02-7unfNccZ601cad5753965.png

當請求進入時,web server將請求轉交給PHP-FPM,PHP-FPM是一個進程池架構的FastCGI服務,內置PHP解釋器。FPM負責解釋執行PHP文件生成響應,最終返回給web server,展現至前端。PHP文件中實現了許多業務邏輯,包括Mysql和Nosql的訪問,調用第三方應用等等。

這樣的結構php-fpm和nginx的配合已經運行得足夠好,但是由於php-fpm本身是同步阻塞進程模型,在請求結束後釋放所有的資源(包括框架初始化創建的一系列對象),導致PHP進程“空轉”(創建<-->銷燬<-->創建)消耗大量的CPU資源,從而導致單機的吞吐能力有限。

每次請求處理的過程都意味着一次PHP文件解析,環境設置等不必要的耗時操作PHP進程處理完即銷燬,無法在PHP程序中使用連接池等技術實現性能優化。

1.2、Swoole運行模式

針對傳統架構的問題,swoole從PHP擴展出發,解決了上述問題,相比於傳統架構,Swoole進程模型最大的特點在於其多線程Reactor模式處理網絡請求,使得其能輕鬆應對大量連接。

除此之外的優點還包括:

全異步非阻塞,佔用資源開銷小,程序執行效率高

程序運行只解析加載一次PHP文件,避免每次請求的重複加載

1.3、使用swoole和傳統php開發的缺點

1、更難上手。這要求開發人員對於多進程的運行模式有更清晰的認識

2、更容易內存泄露。在處理全局變量,靜態變量的時候一定要小心,這種不會被GC清理的變量會存在整個生命週期中,如果沒有正確的處理,很容易消耗完所有的內存。在php-fpm下,php代碼執行完內存就會被完全釋放。

二、註解機制

一般而言,在編程屆中註解是一種和註釋平行的概念,在解釋註解之前我們需要先定義一下 註解 與 註釋 的區別:

註釋:給程序員看,幫助理解代碼,對代碼起到解釋、說明的作用

註解:給應用程序看,註解往往充當着對代碼的聲明和配置的作用,爲可執行代碼提供機器可用的額外信息,在特定的環境下會影響程序的執行。

框架可以基於這些元信息爲代碼提供各種額外功能,本質上註解就是理解註解只是配置的另一種展現方式:

比如通過註解的方式實現權限的控制,就比配置文件當中配置要更加的方便

比如利用註解的方式配置路由、配置定時任務

現有的基於swoole的框架很多都是基於註解開發的,所以我們需要對註解機制有了解,接下來利用代碼來實現下註解

三、容器

3.1、什麼是容器?

容器 就是一個巨大的工廠,用於存放和管理 對象的生命週期,並且能夠解決程序的依賴關係,實現解耦。

3.2簡單的通過代碼理解依賴注入

/**

* 耦合嚴重的寫法

**/

**class** **db** {

 **public** **static** **function** **get_db**() {

 **return** **new** mysqli('127.0.0.1','user','pass','dbname',3306);

 }

}

**class** **post** {

 **private** $db;

**public** **function** __construct($db){

 //假設數據庫驅動發生了變化呢?如果寫死只能直接改動代碼

 **$this**->db =**new** mysqli('127.0.0.1','user','pass','dbname',3306); }

 **public** **function** **get_post**($id){

 **return** **$this**->db->query('SELECT * FROM post WHERE id ='.$id);

 }

}

$post = **new** post();

$post->get_post(12);

/*

*依賴注入的方式

*/

**<?php**

**class** **db** {

 **public** **static** **function** **get_db**() {

 **return** **new** mysqli('127.0.0.1','user','pass','dbname',3306);

 }

}

**class** **post** {

 **private** $db;

 **public** **function** **set_db**(db $db){

 **$this**->db = $db;

 }

 **public** **function** **get_post**($id){

 **return** **$this**->db->query(select xx from xxx);

 }

}

$post = **new** post();

$post->set_db( db::get_db() ); //注入post類依賴的數據庫連接對象,通過類名直接調用靜態方法get_db

$post->get_post(11);

當沒有Ioc/DI容器時

attachments-2021-02-iHbo97rC601cad7574e71.png

當有了IoC/DI的容器後,post類不再主動去創建db類了,如下圖所示:

attachments-2021-02-j2YiFkBo601cad7dcf9d7.jpg

attachments-2021-02-jV3BJHdP601cad8548e4b.jpg

依賴注入:在A類中使用了B類的實例時,B對象的構造不是在A類某個方法中初始化的,而是在A類外部初始化之後以B類的對象傳入進來。這個過程就是依賴注入。所需要的類通過參數的形式傳入的就是依賴注入。

控制反轉IoC(Inversion of Control)是說創建對象的控制權進行轉移,以前創建對象的主動權和創建時機是由自己把控的,而現在這種權力轉移到第三方,比如轉移交給了IOC容器,它就是一個專門用來創建對象的工廠,你要什麼對象,它就給你什麼對象,有了 IOC容器,依賴關係就變了,原先的依賴關係就沒了,它們都依賴IOC容器了,通過IOC容器來建立它們之間的關係,控制反轉意思是說將依賴類的控制權交出去,由主動變爲被動。

3.3、爲什麼說在swoole當中使用容器更有意義?

傳統的php框架沒有常駐內存,因此每次請求進來都需要把用到的類都實例化一次,每次實例化都需要申請內存,當請求處理完之後又需要釋放,具體請參看第一點,所以我們可以在server啓動的時候就把類實例化預先放到內存中,減入對象的創建時間。

一個簡單的bean容器

class BeanFactory{

 private static $container=[];

 public static function set(string $name,callable $func){

 self::$container[$name]=$func;

 }

 public static function get(string $name){

 if(isset(self::$container[$name])){

 return (self::$container[$name])();

 }

 return null;

 }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章