內容來源:2018 年 5 月 20 日,騰訊企點開放平臺技術負責人熊月在「PHPCon China 2018 技術峯會」進行《嵌入式PHP的探索實踐》演講分享。IT 大咖說(微信id:itdakashuo)做爲獨家視頻合做方,經主辦方和講者審閱受權發佈。php
閱讀字數:2410 | 7分鐘閱讀編程
對於擁有不少複雜業務場景的tob領域,「開發效率」和「性能」經常是咱們考慮的兩個主要問題,PHP做爲腳本語言,自己適用於快速開發業務邏輯,同時爲了解決PHP特定的性能瓶頸,通常將C++/PHP結合,在PHP代碼裏調用C/C++擴展。 此次咱們帶來了不一樣思路的探索:將php嵌入到高性能C/C++框架運行,將C/C++框架做爲容器,完美結合php快速開發優點和C/C++高性能特色。Zend Engine提供了一種嵌入式開發模式,咱們利用這一特性使它能夠在C/C++的環境中單獨執行PHP腳本,而且支持多實例運行,能夠在C/C++協程框架中運行。嵌入式PHP也爲在任意C/C++協程框架結合帶來無限可能,包括在C++的客戶端上運行PHP。安全
做爲一門後臺開發語言PHP有着不一樣的發展階段。最開始是你們都比較熟悉的LAMP,接着是PHP-fpm和fastcgi,再日後是swoole,以後在swoole的基礎上又新增了協程。微信
爲了便於理解,在介紹嵌入式PHP以前要先講下SAPI的概念。SAPI即後臺應用程序編程接口,是PHP與其餘應用程序交互的接口。常見的SAPI有cgi、fpm、cli、Apace2 hander,而嵌入式PHP(embed)也是其中一類。swoole
咱們最初的業務框架是基於TSF2.0,底層爲Zend Engine和擴展,擴展最核心的部分是基於swoole。在此之上是TSF PHP層,包含協程調度器、微服務框架、監控管理進程、MVC模式。最上層纔是真正的執行邏輯的PHP腳本。網絡
這樣一套框架存在幾個問題。PHP原生的Generator協程須要配合yield使用,對開發來講不怎麼友好,由於yield的使用時機不太好肯定,尤爲是對於新手。因爲協程調度器是用原生PHP實現的,所以相對其餘語言在性能上會差些,特別是在高併發場景下。還有就是低版本swoole不夠穩定,問題最多的就是在內存泄露這塊。你們都知道騰訊內部有不少公用組件,這些組件接口大可能是用C++實現的,爲此咱們須要作的是用擴展對接PHP與其餘組件,而問題就在於擴展沒法使用上層的PHP協程。多線程
SNG中有個很是有名的C++後臺框架SPP,它是一個高性能的網絡框架,起始於2008年,被普遍的應用於SNG的各個業務線。衆所周知開發效率一直是PHP的長處,性能方面則是短板。因此咱們就在想能不能將SPP和PHP結合起來兼顧高性能和開發效率,嵌入式PHP無疑是很好的結合方案。架構
SPP主要有5個模塊。proxy用來處理新請求,內存隊列是proxy和workgroup交互的內存區域,workgroup是和後臺邏輯腳本交互的模塊,controller做爲控制核心來控制proxy和workgroup的運行狀態,最後是最重要的協程模塊。併發
SPP實際上是基於協程的框架,協程是一個用戶態的多線程概念。在協程切換的時候會涉及內存管理的機制,而Zend沒有這種切換內存資源的機制,只有全局變量和多線程資源隔離的方式。這樣的話要想將SPP和Zend結合起來,就要對Zend進行改造。框架
Zend的源碼大概有60萬行,若是直接改動核心源碼,不光實施起來很麻煩,對以後的升級也會形成問題。最好的辦法是藉助Zend自己的機制對入口進行改造,而不侵入內核。
Zend有多進程和多線程兩種方式,在多線程模式下有一個線程安全的機制ZTS。ZTS本質實際上是對每一個線程的全局資源進行了隔離,與SPP協程的結合就須要用到ZTS,下面是具體步驟。
第一步固然是打開Zend內核ZTS開關,第二步爲了知足協程上下文切換,須要將ZTS中的線程私有變量轉化爲全局數據元素,第三步增長資源入口切換API。作完這三步就完成了Zend和SPP的結合,雖然步驟很少但實際上在作的過程當中仍是會有不少挑戰。
解決告終合問題以後,接下來爲了將整個流程串起來須要有一個執行流程調度器。上圖是整個執行流程,首先SPP經過SAPI進入到Zend中,而後Zend執行PHP腳本,先編譯成OpCode,以後若是有網路IO就會用到協程。協程也能夠基於SPP提供的API來運做,經過Tsrm的全局資源table能夠進行協程切換。
在有這樣一套執行流的狀況下,擴展也能夠依賴SPP的API實現協程調度。
上圖是SPP結合PHP以後的總體架構。最底層是SPP,往上是PHP執行流調度器,中間是PHP內核和擴展,最上層是PHP腳本。這一整套架構以嵌入式的方式結合了SPP和PHP,讓開發者既能夠利用SPP提供的高性能網絡框架,同時也能應用到上層PHP快速開發的特色。
這裏展現的是壓測時候的環境數據,包括機型、壓測工具、壓測方法以及框架的版本等。
這是壓測後得到的實際數據對比,能夠看到SPP-PHP框架相對舊的框架性能上大概有3倍的提高。