Swoole引擎原理的快速入門乾貨

更多內容,歡迎關注微信公衆號:全菜工程師小輝~php

過去一年使用PHP和Java兩種技術棧完成了一個遊戲服務器項目。因爲項目中有高頻的網絡請求,因此PHP技術棧嘗試使用Swoole引擎(基於事件的高性能異步並行網絡通訊引擎)來完成部分遊戲業務。nginx

Swoole的安裝

安裝swoole很簡單,因爲是國人作的項目,不少issue能夠在官網文檔找到答案。安裝分兩種:git

  • 編譯安裝。直接去github或者gitee去下載官方的發行版,編譯安裝後,將so拓展寫入php.ini文件。
  • 容器安裝。swoole引擎應用普遍,因此hub上有不少可用的容器,選擇須要的pull一下便可。
具體操做百度一下便可,網上相關內容不少。

Swoole引擎的優點

  1. 常駐內存。傳統 PHP框架或者單文件,在處理每一個請求以前,都要作一遍加載框架文件、配置的操做,請求完成以後會釋放全部資源和內存,無須擔憂內存泄漏。可是若是請求數量上升,併發很高的時候,快速建立資源,又立刻釋放,會致使 PHP 程序運行效率急劇降低。而使用 Swoole 則沒有這個問題:PHP的代碼加載到內存後,擁有更長的生命週期,這樣創建的數據庫鏈接和其餘大的對象,不被釋放。每次請求只須要處理不多的代碼,而這些代碼只在第一次運行時,被 PHP 解析器編譯,駐留內存。之後都是直接載入 OPCODE ,讓 Zend 引擎直接運行。另外,以前PHP不能實現的,如數據庫鏈接池,緩存鏈接池均可以在Swoole引擎下實現。系統的運行效率會大大提升。
  2. 快速開發。Swoole引擎提供了PHP語言的異步多線程服務器,異步TCP/UDP網絡客戶端,異步MySQL,異步Redis,數據庫鏈接池,AsyncTask,消息隊列,毫秒定時器,異步文件讀寫,異步DNS查詢。 Swoole內置了Http/WebSocket服務器端/客戶端、Http2.0服務器端。
  3. 協程編程模式。Swoole4可使用徹底同步的代碼實現異步程序。PHP代碼無需額外增長任何關鍵詞,底層自動進行協程調度,實現異步IO。

Swoole引擎的流程解析

Swoole運行的流程圖以下:github

Swoole的運行圖

Swoole中的線程或進程

結構圖以下:數據庫

Swoole的線程圖

Swoole引擎分爲兩種模式:單線程模式和進程模式。本文只討論進程模式。具體二者區別官方文檔中有說明。

Master進程

用於處理swoole核心事件,好比來自客戶端的鏈接,本地通信的管道。master進程裏有多個線程,每一個線程運行了一個epol函數的實例。(因爲Worker進程並非由Master進程fork出來的,因此可能會出現強行kill Master進程後,Worker進程依舊存在)apache

Reactor線程

Swoole的主進程是一個多線程的程序。其中有一組很重要的線程,稱之爲Reactor線程。它就是真正處理TCP鏈接,收發數據的線程。
Swoole的主線程在Accept新的鏈接後,會將這個鏈接分配給一個固定的Reactor線程,並由這個線程負責監聽此socket。在socket可讀時讀取數據,並進行協議解析,將請求投遞到Worker進程。在socket可寫時將數據發送給TCP客戶端編程

Manager進程

swoole中worker/task進程都是由Manager進程Fork並管理的。
子進程結束運行時,manager進程負責回收此子進程,避免成爲殭屍進程。並建立新的子進程
服務器關閉時,manager進程將發送信號給全部子進程,通知子進程關閉服務
服務器reload時,manager進程會逐個關閉/重啓子進程segmentfault

Worker進程

Swoole提供了完善的進程管理機制,當Worker進程異常退出,如發生PHP的致命錯誤、被其餘程序誤殺,或達到max_request次數以後正常退出。主進程會從新拉起新的Worker進程。 Worker進程內能夠像普通的apache+php或者php-fpm中寫代碼。不須要像Node.js那樣寫異步回調的代碼。緩存

各進程的回調函數

Master內的回調函數:服務器

  • onStart
  • onShutdown

Worker進程內的回調函數

  • onWorkerStart
  • onWorkerStop
  • onConnect
  • onClose
  • onReceive
  • onFinish

TaskWorker進程內的回調函數

  • onTask
  • onWorkerStart

Manager進程內的回調函數

  • onManagerStart
  • onManagerStop

Reactor、Worker、TaskWorker的關係

能夠理解爲Reactor就是nginx,Worker就是php-fpm。Reactor線程異步並行地處理網絡請求,而後再轉發給Worker進程中去處理。Reactor和Worker間經過UnixSocket進行通訊。
在php-fpm的應用中,常常會將一個任務異步投遞到Redis等隊列中,並在後臺啓動一些php進程異步地處理這些任務。Swoole提供的TaskWorker是一套更完整的方案,將任務的投遞、隊列、php任務處理進程管理合爲一體。經過底層提供的API能夠很是簡單地實現異步任務的處理。另外TaskWorker還能夠在任務執行完成後,再返回一個結果反饋到Worker。
Swoole的Reactor、Worker、TaskWorker之間能夠緊密的結合起來,提供更高級的使用方式。一個更通俗的比喻:假設Swoole應用服務器是一個工廠,那Reactor就是銷售,接受客戶訂單。而Worker就是工人,當銷售接到訂單後,Worker去工做生產出客戶要的東西。而TaskWorker能夠理解爲行政人員,能夠幫助Worker幹些瑣事,讓Worker專心工做。
底層會爲Worker進程、TaskWorker進程分配一個惟一的ID。不一樣的Worker和TaskWorker進程之間能夠經過sendMessage接口進行通訊。

實際項目中的各進程線程的分工:

  • Manager進程:負責管理worker進程,建立或回收
  • Worker進程:遊戲邏輯處理
  • taskWorker進程:向客戶端髮網絡包、關閉長期不活躍的tcp鏈接

Swoole版本兼容性

該項目開發階段使用的swoole引擎版本1.9.6,後來因爲測試環境安裝成了4.3.2版本,因此嘗試業務代碼做調整。不過swoole的向下兼容很值得佩服的是,這過程當中居然只發現了一處代碼不兼容的問題:是有關swoole_server的一項配置參數,在原來版本採用了魔鬼數字進行配置的,可是到新版本,這個數字沒有被宏定義,後來經過查看swoole源碼找到了宏定義組,而後修改了這處配置。(不過版本升級順利也是基於swoole的業務代碼比較少,因此僅供參考)

哎呀,若是個人名片丟了。微信搜索「全菜工程師小輝」,依然能夠找到我

相關文章
相關標籤/搜索