php爲什麼要使用swoole?

現在的PHPer,得益於前端的快速發展、以及前後端分離的理念普及,已經有很多人都從渲染模板的工作中解脫出來了。

隨着微服務(服務化)的盛行,讓swoole如虎添翼,php不會越來越衰頹,swoole將撐起php的另一片天。

隨着PHP編程語言被越來越多的人使用,更多人瞭解到swoole的存在,有的人說swoole是披着PHP外衣的C程序,但是swoole並不是一個簡單的PHP框架,正如swoole官方首頁的第一句話“重新定義PHP”,千萬不要用舊有php的思想來寫swoole代碼!

Swoole的發展和完善,也促成了大量PHPer的自我提升,swoole重新激活了PHP,php成就了swoole!

一、什麼是Swoole?
Swoole 是“面向生產環境的 PHP 異步網絡通信引擎”,首先 Swoole 它是一個網絡應用的開發工具,它支持 Http、TCP、UDP、WebSocket,它的使用目前一些基於 Swoole 的框架開發,從開發習慣上和傳統的TP、LV 框架相差不多。

二、Swoole給PHP帶來了什麼?

1、類NodeJS的異步:

備胎倒不是沒有,最有名的當屬Workerman和ReactPHP,兩者都提供了類NodeJS的異步能力,還是用PHP實現的,相比Swoole顯著降低了內存泄露和崩潰的機率。

當異步回調面臨複雜業務邏輯的時候,回調寫在嵌套和循環裏就不是那麼直觀了,不但需要自己保存context,有時不得不寫成遞歸的形式,如果要在callback chain中跳來跳去就更燒腦了。Swoole協程徹底解決了複雜業務時的異步回調地獄。這點沒有替代方案。

2、類Go的協程

Swoole 的協程客戶端必須在協程的上下文環境中使用。

// 第一種情況:Request 回調本身是協程環境
$server->on('Request', function($request, $response) {
    // 創建 Mysql 協程客戶端
    $mysql = new Swoole\Coroutine\MySQL();
    $mysql->connect([]);
    $mysql->query();
});

// 第二種情況:WorkerStart 回調不是協程環境
$server->on('WorkerStart', function() {
    // 需要先聲明一個協程環境,才能使用協程客戶端
    go(function(){
        // 創建 Mysql 協程客戶端
        $mysql = new Swoole\Coroutine\MySQL();
        $mysql->connect([]);
        $mysql->query();
    });
});

Swoole 的協程是基於單線程的, 無法利用多核CPU,同一時間只有一個在調度。

// 啓動 4 個協程
$n = 4;
for ($i = 0; $i < $n; $i++) {
    go(function () use ($i) {
        // 模擬 IO 等待
        Co::sleep(1);
        echo microtime(true) . ": hello $i " . PHP_EOL;
    });
};
echo "hello main \n";

// 每次輸出的結果都是一樣
$ php test.php 
hello main 
1558749158.0913: hello 0 
1558749158.0915: hello 3 
1558749158.0915: hello 2 
1558749158.0915: hello 1

Swoole 協程使用示例及詳解

// 創建一個 Http 服務
$server = new Swoole\Http\Server('127.0.0.1', 9501, SWOOLE_BASE);

// 調用 onRequest 事件回調函數時,底層會調用 C 函數 coro_create 創建一個協程,
// 同時保存這個時間點的 CPU 寄存器狀態和 ZendVM stack 信息。
$server->on('Request', function($request, $response) {
    // 創建一個 Mysql 的協程客戶端
    $mysql = new Swoole\Coroutine\MySQL();
    
    // 調用 mysql->connect 時發生 IO 操作,底層會調用 C 函數 coro_save 保存當前協程的狀態,
    // 包括 Zend VM 上下文以及協程描述的信息,並調用 coro_yield 讓出程序控制權,當前的請求會掛起。
    // 當協程讓出控制權之後,會繼續進入 EventLoop 處理其他事件,這時 Swoole 會繼續去處理其他客戶端發來的 Request。
    $res = $mysql->connect([
        'host'     => '127.0.0.1',
        'user'     => 'root',
        'password' => 'root',
        'database' => 'test'
    ]);
    
    // IO 事件完成後,MySQL 連接成功或失敗,底層調用 C 函數 coro_resume 恢復對應的協程,恢復 ZendVM 上下文,繼續向下執行 PHP 代碼。
    if ($res == false) {
        $response->end("MySQL connect fail");
        return;
    }
    
    // mysql->query 的執行過程和 mysql->connect 一致,也會進行一次協程切換調度
    $ret = $mysql->query('show tables', 2);
    
    // 所有操作完成後,調用 end 方法返回結果,並銷燬此協程。
    $response->end('swoole response is ok, result='.var_export($ret, true));
});

// 啓動服務
$server->start();

3、內置Redis/Http等協議

內置協議,Swoole支持的協議最多最全,即使不支持的,也有很大機率使用HOOK自動支持起來。

4、常駐內存,避免重複加載帶來的性能損耗,提升海量性能

5、現有阻塞庫異步/協程化,提高對IO密集型場景併發處理能力(如:微信開發、支付、登錄等)。

現有阻塞庫的異步/協程化,這點也沒有替代方案,Workerman和ReactPHP裏非要用阻塞庫的時候,只能走多線程或者多進程方案,編程不知道要麻煩多少。

三、使用swoole必須要掌握的技能

1、多線程編程

2、進程間通信

3、網絡協議TCP/UDP的認知

4、PHP的各項基本技能

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