Swoole-2.0.1-Alpha 已釋出,提供PHP原生協程支援

錢曙光發表於2016-08-03

Swoole-2.0 提供了PHP原生協程排程器,PHP程式碼可以按照同步方式編寫,底層引擎使用非同步IO,排程器會在IO完成後自動切換PHP函式呼叫棧。

內建協程不依賴PHP的Yield/Generator語法,實現了真正的同步程式碼,非同步IO。Swoole-2.0相容Swoole-1.0所有現存特性,同時支援同步阻塞、非同步非阻塞回撥、協程 3 種 IO 模型。

協程可以理解為使用者態執行緒,通過協作而不是搶佔來進行切換。相對於作業系統程式或者執行緒,協程所有的操作都可以在使用者態完成,建立和切換的消耗更低。Swoole可以為每一個請求建立對應的協程,根據IO的狀態來合理地排程協程。

Swoole-2.0內建協程的優勢:

  1. 開發者可以使用最傳統的PHP同步編碼方式即可實現非同步IO。過去使用Node.js和Swoole1.0編寫非同步程式時必須使用巢狀回撥,開發效率低,邏輯複雜之後開發維護都很困難。現在使用Swoole-2.0內建協程可以輕鬆編寫非同步程式,徹底告別Callback Hell

  2. 由於Swoole-2.0是在底層封裝了協程,所以對比其他的PHP協程框架,如TSFZan,開發者不需要額外使用yield關鍵詞來標識一個協程IO切換操作,所以不再需要對yield的語義進行深入理解以及對每一級的呼叫都修改為yield,這極大的提高了開發效率。

  3. Swoole-2.0除了支援常見的如TCP、UDP、HTTP、Redis、MySQL協程客戶端之外,還支援併發Client,可以同時併發執行多個不同型別的協程客戶端呼叫,時間為Max(耗時最長Client的時間)。而Go語言需要使用非常複雜的goroutine+chan+select才能實現。Swoole-2.0的併發呼叫使用更加簡單。

主要特性:

  • 底層內建協程,同步的程式碼,非同步的IO
  • TCP/UDP/UnixSocket協程客戶端Swoole\Coroutine\Client
  • Http/WebSocket協程客戶端Swoole\Coroutine\HttpClient
  • Redis協程客戶端Swoole\Coroutine\Redis
  • MySQL協程客戶端Swoole\Coroutine\MySQL
  • 併發Client
  • 支援非同步超時
  • 預設開啟名稱空間

要求:

  • 需要PHP5.5或更高版本
  • 暫時不支援PHP7
  • 伺服器端基於Swoole\Server或者Swoole\Http\Server進行開發,目前僅支援在onRequetonReceiveonConnect回撥中使用協程

安裝方式:

Swoole-2.0需要通過新增--enable-coroutine編譯引數啟用協程能力,示例如下:

phpize
./configure --with-php-config={path-to-php-config}  --enable-coroutine
make
make install

新增編譯引數,swoole server將切換到協程模式

使用示例

TCP協程客戶端

$client = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
$client->connect('127.0.0.1', 95010.5)
//呼叫connect將觸發協程切換
$client->send("hello world\n");
echo $client->recv();
//呼叫recv將再次觸發協程切換
$client->close();

Http協程客戶端

$cli = new Swoole\Coroutine\Http\Client('127.0.0.1', 80);
$cli->setHeaders([
    'Host' => "localhost",
    "User-Agent" => 'Chrome/49.0.2587.3',
    'Accept' => 'text/html,application/xhtml+xml,application/xml',
    'Accept-Encoding' => 'gzip',
]);
$cli->set([ 'timeout' => 1]);
$cli->get('/index.php');
echo $cli->body;
$cli->close();

Redis協程客戶端

$redis = new Swoole\Coroutine\Redis();
$redis->connect('127.0.0.1', 6379);
$val = $redis->get('key');

MySQL協程客戶端

$swoole_mysql = new Swoole\Coroutine\MySQL();
$swoole_mysql->connect(['host' => '127.0.0.1', 
    'user' => 'user',
    'password' => 'pass', 
    'database' => 'test',
]);
$res = $swoole_mysql->query('select sleep(1)');

併發呼叫

$tcpclient = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
$tcpclient->connect('127.0.0.1', 95010.5)
$tcpclient->send("hello world\n");

$redis = new Swoole\Coroutine\Redis();
$redis->connect('127.0.0.1', 6379);
$redis->setDefer();
$redis->get('key');

$mysql = new Swoole\Coroutine\MySQL();
$mysql->connect(['host' => '127.0.0.1',
    'user' => 'user',
    'password' => 'pass',
    'database' => 'test',
]);
$mysql->setDefer();
$mysql->query('select sleep(1)');

$httpclient = new Swoole\Coroutine\Http\Client('0.0.0.0', 9599);
$httpclient->setHeaders(['Host' => "api.mp.qq.com"]);
$httpclient->set([ 'timeout' => 1]);
$httpclient->setDefer();
$httpclient->get('/');

$tcp_res  = $tcpclient->recv();
$redis_res = $redis->recv();
$mysql_res = $mysql->recv();
$http_res  = $httpclient->recv();

通常,如果一個業務請求中需要做一次redis請求和一次mysql請求,那麼網路IO會是這樣:

redis發包->redis收包->mysql發包->mysql收包

以上流程網路IO的時間就等於 redis網路IO時間 + mysql網路IO時間。

而對於協程版本的Client,網路IO可以是這樣:

redis發包->mysql發包->redis收包->mysql收包

以上流程網路IO的時間就接近於 MAX(redis網路IO時間, mysql網路IO時間)。

現在支援併發請求的Client有:

  • Swoole\Coroutine\Client
  • Swoole\Coroutine\Redis
  • Swoole\Coroutine\MySQL
  • Swoole\Coroutine\Http\Client

除了Swoole\Coroutine\Client,其他Client都實現了defer特性,用於宣告延遲收包。

注意事項

  1. 全域性變數:協程使得原有的非同步邏輯同步化,但是在協程的切換是隱式發生的,所以在協程切換的前後不能保證全域性變數以及static變數的一致性。

  2. 請勿在下列場景中呼叫協程客戶端:

    • 解構函式__destruct()
    • 魔術方法__call()
  3. 當前版本為Alpha預覽版本,不建議在生產環境上使用

使用新版本

宣告:本文CSDN作者原創投稿文章,未經許可禁止任何形式的轉載。
作者:韓天峰,車輪互聯總架構師、Swoole開源專案創始人、PHP語言官方擴充套件開發組成員。曾在騰訊朋友網、易迅商城、淘寶搜尋的負責PHP平臺技術研發工作。
責編: 錢曙光,關注架構和演算法領域,尋求報導或者投稿請發郵件qianshg@csdn.net,另有「CSDN 高階架構師群」,內有諸多知名網際網路公司的大牛架構師,歡迎架構師加微信qshuguang2008申請入群,備註姓名+公司+職位。


2016年8月12日-13日,由CSDN重磅打造的網際網路應用架構實戰峰會運維技術與實戰峰會將在成都舉行,目前18位講師和議題已全部確認。兩場峰會大牛講師來自阿里、騰訊、百度、京東、小米、樂視、聚美優品、YY互娛、華為、360等知名網際網路公司,一線深度的實踐,共同探討高可用/高併發/高效能系統架構設計、電商架構、分散式架構、運維工具研發與實踐、運維自動化系統的構建、DevOps、雲上的運維案例分析、虛擬化技術、應用效能檢測與管理、遊戲行業的運維實踐等,將和與會嘉賓共同探討「構建更安全、更高效能、更穩定的架構和運維體系」等領域的話題與技術。【八折優惠中,點選這裡搶票,欲購從速。】

相關文章