天天看點

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 在未來可預見的很長時期内不會沒落,它會作為中小公司的快速原型語言和大公司的粘合層語言長期存在。

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