再談 PHP 未來之路

林子er發表於2020-05-06

前段時間我寫過一篇博文《phper:敢問路在何方》,分析了 PHPer 的困境以及 PHP 程式設計師的學習、進階突破之路。同時我在知乎上也發過類似的提問。從大家的評論和回答看,大體分為以下幾種情況:

  • 認為 PHPer 的困境跟 PHP 語言無關,而取決於程式設計師自身的水平、能力;

  • 認為 PHP 語言本身就不行,只適合初創企業、外包公司使用,程式設計師不應該從事 PHP 開發,應當選擇更有前途的如 java、go 等語言;

  • 認為 PHP 生態不行;

我在前面那篇文章中重點討論了程式設計師(PHPer)面臨的困境以及進階之路,就 PHP 這門語言本身並沒有做過多分析。文末,我得出的結論是“PHPer 的唯一出路是不要把自己定位成 PHPer”,這句話從狹義來理解,確實對 PHP 本身抱有悲觀態度,但從廣義理解,任何一個程式設計師,無論他使用的主程式語言是什麼(哪怕是 java、c++),要達到一定的高度,就不能把自己定位成那門語言的專職獵手。

寫完那篇文章後,看到一些留言,以及知乎的一些回答,我便陷入了對 PHP 語言本身的思索:這門語言現在到底處於生命週期的哪個階段?其定位到底是怎樣的?諸如 PHP7、Swoole 的出現到底能給 PHP 帶來怎樣的變化?

這些問題又讓我失眠了一整夜,現在,我就自己的思考寫下此文。

當我們談論語言的時候,我們到底是在談論什麼?

當我們拿 PHP 和 java 進行比較的時候,我們往往就兩門語言本身進行比較,如一個是弱型別一個是強型別,一個是陣列打天下一個是各種資料結構,甚至連花括號是不是換行寫都會被討論一番。但它們真正的區別並非這些。

當我們談論一門語言的時候,我們是在談它的生態

“生態”一詞在百度百科上的解釋是:“生態一詞,現在通常是指生物的生活狀態。指生物在一定的自然環境下生存和發展的狀態,也指生物的生理特性和生活習性。生態(Eco-)一詞源於古希臘字,意思是指家(house)或者我們的環境”。

生態具有如下特點:

  1. 生態是系統,由多個部分組成的完整體;

  2. 生態是開放系統;

  3. 生態具有動態平衡性;

  4. 維持其動態平衡的是源動力,源動力一旦消失,生態即消亡。例如地球生態系統的源動力是太陽能;一旦太陽消失,地球生態則不復存在(想想《流浪地球》);

一種生物的生存狀態不取決於生物自身,而取決於環境,就如恐龍的滅絕並非恐龍自身退化了,而是環境改變了(或者說恐龍的進化趕不上環境的變化)。

一門語言的興衰不取決於它自身,而取決於環境,具體來說是環境中源動力的強弱。

PHP 應 Web 而生,考查其興衰得考查網際網路的發展。

一般認為網際網路大致經歷了三個階段:

  • 階段一:Web1.0 時代,傳統的內容網站,如企業官網、行業入口網站等,網站自身產生內容,使用者僅檢視內容;

  • 階段二:Web2.0 時代,使用者參與內容的建立,如論壇、部落格。階段一和階段二都是內容為主,服務為輔(雖然內容的產生方式有所不同);

  • 階段三:移動網際網路時代,資訊流、內容與服務並存;

以上三個階段的演化中,使用者參與度越來越高,互動方式越來越豐富,網站流量越來越大。

階段一和階段二是 PHP 的黃金時代,從階段二開始悄悄發生變化,而到了階段三,PHP 的黃金時代基本結束。

PHP 這門語言的特點是“簡單、實用”,入行門檻極低,一個程式設計小白,一週入門,兩天出個網站。一個典型的例子,在資料結構上,不像其他語言有 Array、List、Map、Set,PHP 一個 Array 搞定所有的情況。

PHP 的這種“簡單”是通過犧牲效能為代價的。由於需要簡單,不能有各種型別限制,PHP 必須是動態語言;由於需要簡單,能封裝則封裝,一個 file_x_contents 搞定檔案(甚至是網路)讀寫(該函式是一次性將檔案全部載入到記憶體中,很多人開發不考慮其侷限性而用在所有場景,導致記憶體溢位);由於 Array 承包了所有集合型資料結構,其底層需要做各種處理不說,業務層也無法自主選擇更合適的資料結構做針對性的優化(雖然後來 SPL 提供了一些基本資料結構)。

PHP 的這種“簡單”還犧牲了另一樣東西:程式設計師的專業素質。PHP 程式設計師根本不需要去了解真正的 Array 和 List 有什麼區別,也不需要去管資料流、緩衝區。從長期來看,這一點是致命的,它使得 PHP 生態中的重要一環很脆弱,很可能是導致 PHP 最終衰落的真正因素。

在 Web1.0 時代,一方面內容產生者是網站自身,另一方面人們只能通過桌面瀏覽器上網,這些因素使得這個階段絕大部分公司根本不會遇到高併發等效能問題,而且業務的簡單性使得單體應用足以應付一切,因而這個階段 PHP 的缺陷根本不足為患。於是,PHP 的優勢(簡單上手、快速開發)讓這門語言大行其道,什麼 JSP、ASP,根本不是對手。那個時期,人們談論 java、C# 時,基本是在談 ERP,只有 PHP 才是 Web。

到了 2.0 時代,論壇、部落格、SNS 的出現,使得使用者建立內容成為可能。由於使用者的積極參與,網站伺服器流量相對於 1.0 時代有了突增,特別是 SNS 的資訊流特性,使得伺服器面臨相當的挑戰。不過由於人們仍然是通過 PC 瀏覽器上網,在一定程度上限制了使用頻率。這個時期,一些大公司針對 PHP 的效能缺陷做了自己的改造,如新浪的各種 c 擴充套件(yaf、yar 等),facebook 的 HVVM。

在這兩個黃金時代,PHP 世界湧現了大量的經典開源專案:WordPress、ecshop、Magento、Discuz、Thinkphp、Yii 等。

徹底結束掉 PHP 黃金時代的是移動網際網路的到來。iphone 改變了世界,也改變了 PHP 的命運。

移動網際網路時代,人們隨時隨地都能上網,而且幾乎每人一部手機,這帶來的直接效果就是 Web 使用需求出現了數量級的增長。另外,移動網際網路時代的另一個特點是內容+服務的一體化,網站不再只是提供內容,還提供服務(如各種 O2O),因而在使用頻率、互動體驗上的需求都大大增強。

舉個例子,在 1.0 時代,瀏覽器和伺服器根本不需要建立長連線,2.0 時代,由於資訊流的出現,要求有輪詢機制,但由於當時無論是瀏覽器還是 PHP 都不支援長連線,人們想了各種奇淫技巧來實現輪詢。移動網際網路時代,瀏覽器端有了 WebSocket,悲劇的是 PHP 本身卻不支援 WebSocket(由於 PHP 的執行機制是一次請求後程式就結束了,在語言核心層面無法提供 WebSocket 機制。要想在核心層面支援 WebSocket,必須改造 PHP 的整個執行機制,這幾乎是不可能的)。

至此,一方面 PHP 的效能問題成了致命問題,另一方面 PHP 各種“方便”的機制(如由 php-fpm 代替 PHP 指令碼自身的常駐程式)滿足不了新的場景需求,反倒成了桎梏。

在移動互聯、萬物成網的大背景下,微服務應運而生。一般認為微服務本身並非新的概念,早期的 SOA 就有其身影。不過我們談論一個概念本身到底新不新沒有意義(就好比有人認為中國的勾三股四弦五的發現比希臘的畢達哥拉斯定理要早,於是認為該定理是中國人發現的;有人認為中國的陰陽學說含有二進位制思想,便認為二進位制是中國人發明的),重要的是一個概念何時形成了一套完整的體系,以及是如何來解決實際問題的。

微服務架構是相對單體架構來說的。我們先說說微服務的缺點:服務間呼叫關係複雜、難治理、問題排查複雜、分散式事務問題等。既然有這麼多缺點,為啥微服務架構當今能大行其道?原因在於單體架構解決不了當今面臨的問題:巨大而複雜的業務群、高併發、高可用的系統需求。

微服務給 PHP 帶來什麼呢?

當我們將單體架構拆解成一個個小的服務的時候,我們來考查一下程式語言的選擇,看看 PHP 還是不是最佳選擇:

  • 首先微服務要輕量化。

  • 其次服務要被多個業務端呼叫,其執行要足夠快。

  • 另外當服務間通訊非常頻繁時,通訊協議要保持高效,此時 HTTP 協議並非最佳,很多公司傾向於 RPC 協議。

  • 後端服務相對於前面的業務層來說,變動頻率相對要低一些,因而可以適當地犧牲一些開發效率。

  • 要有較成熟的生態和框架支援(成熟的服務治理生態)。

從上面幾點來看,PHP 並非最佳選擇:

  • 傳統的 PHP 架構是 nginx + php-fpm + PHP script,顯然不夠輕量,成百上千個服務都馱著這麼厚厚的一層殼,顯然存在資源浪費問題。

  • PHP 作為指令碼語言,由於存在指令碼解析消耗,執行速度上趕不上 java、C++ 等靜態語言(不過在 PHP 引入 opcode cache 後情況得到了很大改善,而且對於 Web 來說大部分時候都是 I/O 密集型操作,語言本身的效能影響對於絕大部分的公司來說並非主要問題————不過一方面心理學研究表明人類的認知並非完全理性的,人們認為 PHP 比 java 效能差那就是差,不管實際差多少(這就好比我們認為大品牌的東西一定比小品牌的好一樣,程式語言的世界也有品牌效應))。

  • PHP 核心沒有提供現成的 RPC 方案,但可以通過擴充套件解決,這不是問題。問題是傳統的 PHP 架構(nginx + fpm + script,一次請求完成後工作程式即結束)並不能很好地應用 RPC 通訊的優勢。

  • 在生態和框架上,Swoole 貌似是個不錯的選擇,不過 Swoole 的微服務生態目前尚不成熟。

  • 大部分的 PHP 程式設計師對服務化比較陌生(以及對效能、可靠性等非功能性需求的普遍漠視),上手較慢。

綜合考慮,大部分公司進行服務化的時候,會選用主流靜態語言(java、C++ 以及後起之秀 golang 等)做服務,PHP 更多是來開發中間的業務聚合系統來呼叫這些服務。

至此,PHP 走下“神壇”,官方那句“PHP 是有史以來最好的語言”永成過去式。

不少人認為,PHP7 和 Swoole 給 PHP 在服務化時代帶來新希望,因為理論上,上面提到的問題 PHP7 和 Swoole 都能較好的解決。

首先 PHP7 帶來了極大的效能提升,而且引入強型別、嚴格模式等新特性,使得 PHP 越來越像強型別語言。其次 Swoole 的出現使得 PHP 很容易像 java、go 那樣實現常駐程式服務而不需要依賴 nginx + php-fpm,那麼 由“nginx + php-fpm + script” 的 CGI 模式在服務化時遇到的問題也都得到了很好的解決。

那麼,PHP7(以及即將到來的 PHP8 的 JIT 特性)和 Swoole 能給 PHP 帶來第二個黃金時代嗎?

個人認為不能。還是那句話,當我們談論語言時,實際上是在談論生態。

程式語言的生態系統中有個很重要的角色:開發者群體。PHP 自出生時的目標就是“簡單、強大、實用”,實現了高度的封裝,讓開發人員專心面對業務。這對工程是好事,對開發人員的成長(以及開發人員生態)來說卻不是。絕大部分的 PHPer 都是業務工程師,幾乎所有工作都是各種業務的 CRUD,很少涉及稍底層的東西,也鮮有關乎設計、架構的。在我周圍的,以及面試遇到的,大部分人根本不瞭解設計模式、資料結構、演算法、計算機原理,寫出來的程式碼也僅僅是實現了業務的功能性需求,很少考慮非功能性需求。另外,在傳統 PHP 的 CGI 模式下,PHP 指令碼並不需要考慮自我恢復、自我保護能力如限流、重試、非同步等這些在微服務架構下必須考慮的東西。

另外,由於大部分 PHP 程式設計師平時都是使用 MVC 框架提供的功能實現 CRUD,較少進行物件建模(PHP 並非生來就是面嚮物件語言,OO 特性是後面加進去的),導致大部分有相當工作經驗的 PHPer 的建模能力都很弱,而微服務的一個重要工作就是對單體專案按業務領域進行拆分、建模,這對 PHPer 來說是個相當大的挑戰。

一個結果是,PHP 程式設計師普遍專業素質都很弱,根本勝任不了複雜的系統架構————這裡的複雜性有兩個層面:技術層面和業務層面。

PHP7 和 Swoole 雖然彌補了語言自身的短板,卻彌補不了生態中非語言部分的缺陷。有人認為這些缺陷是歷史造成的,不能代表未來。萬物的生命都是連續的、演化的,歷史往往決定了未來,雖然身處現在的我們察覺不出。既然 PHP 生態在解決複雜系統問題時不具備優勢,那麼公司就會自然而然地選擇其它更具優勢的生態系統,自此便形成噁心迴圈(現實中我們遇到的情況是,很多使用 PHP 作為主要語言的中小公司業務規模上來後,不得不從外面聘請架構師,這些架構師大部分都是 java 出身,到公司第一件事就是強行 PHP 轉 java)。

有人可能覺得我是 PHP 黑,畢竟我也沒有做過嚴格的調查來得出上面的結論。但我們可以通過一些現象管中窺豹:

  • 我們可以很容易找到用 java、C++ 寫的設計模式、資料結構與演算法方面的暢銷書,卻幾乎找不到 PHP 的。

  • 我們在部落格園、CSDN 等技術部落格上能看到大量 java、C++、C# 程式設計師的部落格,卻很少看到 PHP 的。

  • 我們看到技術部落格上大量 java 程式設計師在談論各種設計、服務、“三高”架構,卻很少見到 PHP 的。

  • 我們能看到 java、C++ 程式設計師到處參加各種技術峰會,卻很少見到 PHPer(除了 PHP 自己的專項會議)。

你會覺得僅憑 PHP7 與 Swoole 能讓幾乎不談設計模式、不研究資料結構與演算法、很少寫部落格、很少參加峰會的 PHPer 們開拓出一片服務化的新天地嗎?

PHP 曾經輝煌過,在移動網際網路之前,在單體為王的時代,就像 Delphi 在 Windows 桌面應用為王的時代取得的輝煌一樣。現實的需求是語言生態系統的源動力,當需求發生不可逆轉的改變時,午日終將西傍。

那麼,接下來的問題是:PHP 會很快沒落嗎?

這個問題實際是在問:如今 PHP 是否還在某些場景下具有優勢(即是否還存在現實需求這一源動力)?

PHP 的優勢是簡單、門檻低、實現功能快捷,很適合如下場景:

  • 業務、系統相對簡單,無需服務化;
  • 對效能不是很敏感;
  • 需要快速實現、快速迭代;

在上面這些場景下,微服務(以及 java、C++ 等靜態語言)的優點並不能彌補其缺點,因而推薦使用單體架構或者簡單的服務化(僅僅進行主要服務拆分,並不引入複雜的服務治理體系),這種情形下 PHP 的優勢就顯現出來了。一般中小公司正是滿足上面的場景,因而我們發現即使是在移動網際網路時代 PHP 輝煌不再,但仍有大量中小公司採用 PHP 作為核心開發語言。

另外一個事實是,由於所有的大公司都是由小公司成長來的,在公司規模尚小的時候,他們大多也是採用 PHP 作為核心語言的,規模成長後,雖然 PHP 的各種短板阻礙了系統的發展,但由於已經有大量的 PHP 專案,完全重新用其他語言開發一遍不太現實,因而他們會採用各種優化手段,比如編寫 PHP 擴充套件或者將 PHP 編譯成某種靜態語言(如 C++),或者將單體專案中的某些核心功能拆解成服務,單體專案呼叫後端服務介面————這種情況下,PHP 專案成了粘合層。

將 PHP 作為粘合語言的不光是因為歷史遺留問題,還有不少公司新專案也會採用這種架構,這樣既充分利用了 PHP 的開發效率(因為粘合層往往比較靠前端,需求變動較頻繁,開發效率是必須要考慮的重要因素),也保證了核心服務的效能。

那麼,接下來的問題是,作為快速原型語言粘合層語言,有沒有其他語言比 PHP 更具優勢?

至少國內不用談 Python 和 RoR(在國外這兩者在 Web 開發上的佔有率也不及 PHP),Python 程式設計師的重心已轉大資料、人工智慧了, RoR 至少在國內一直不溫不火,在程式設計師的招聘上比 PHP 要難很多。

nodejs 曾經被認為是 PHP 的最大對手,一個很大的原因是人們認為如果一個公司使用 nodejs 作為後端語言,那麼他只需要一樣技術棧(前後端都是 js 程式設計師,而 js 程式設計師和 PHP 一樣一抓一大把),體現了莫大的成本優勢。但事實是 nodejs 並沒有對 PHP 造成根本威脅,未來也不太可能會,原因是持上面觀點的人認為統一技術棧就一定能節約成本,但這是個偽命題。一門語言具有解決某個問題的能力不代表人們就一定會拿它去解決問題,就好比 PHP 也能進行 socket 程式設計,但很少公司在生產環境大規模使用 PHP 編寫伺服器。js 天生就是 Web 前端語言,因而絕大部分 js 程式設計師都是一直做前端開發的,而前端開發和後端開發模式上有很大不同。前端在很長一段時間都是面向 DOM 程式設計,即使是有了模組化、React 這些新玩法後,前端開發的重心仍然是事件驅動的互動式程式設計。後端開發的重心在於建模(即使不對業務進行物件建模,也至少需要面向資料庫進行資料建模)以及業務邏輯的實現,做後端開發,資料庫、Linux 伺服器是繞不開的,而這兩者恰恰是大部分前端程式設計師所缺乏的(換句話說,要招一個既很熟悉前端開發又很熟悉後端開發的 js 程式設計師是非常難的)。結果就是,招一個 js 程式設計師用 nodejs 開發後端系統,其成本遠大於招一個 PHPer。

因而,PHP 在未來可預見的很長時期內不會沒落,它會作為中小公司的快速原型語言和大公司的粘合層語言長期存在。

另一個結論是:Python、Ruby On Rails、nodejs 這些語言雖然不會對 PHP 造成根本威脅,但會跟 PHP 一同在 Web 開發領域長期存在————因為它們的源動力是相同的,而 PHP 相對於它們的優勢又不足以完全抹殺掉它們的存在。

總結:

最後,我將上面的分析總結成四個論斷:

  • 論斷一:PHP 在移動網際網路到來之前出現過黃金時期,如今輝煌不再;
  • 論斷二:PHP 在未來可預見的很長時期內不會沒落;
  • 論斷三:後黃金時代 PHP 的定位:中小公司的快速原型語言以及大公司的中間粘合層語言;
  • 論斷四:PHP7 和 Swoole 讓 PHP 在和其他同層級語言(如 Python、RoR、nodejs)的競爭中保持優勢,但無法給 PHP 帶來根本的變化(無法改變 PHP 的定位);

相關文章:《phper:敢問路在何方》

相關文章