現在的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的各項基本技能