淺談從PHP遷移至Golang(基礎篇)

淺談從PHP遷移至Golang(基礎篇)

1、Why Not PHP

使用PHP構建的WEB程式,隨著業務發展到一定體量之後,都不得不面臨以下一些問題:

業務功能不斷擴張,如何避免某單一業務功能故障影響整體,維持系統健壯性

業務邏輯複雜度不斷上升,如何解耦與模組化,降低系統複雜性

網站訪問量不斷攀升,如何實現高併發,實現系統高可用性

計算密集型業務的出現,如何快速適應需求,提升網站效能

。。。

對於PHP而言,在業務發展初期,可以快速實現業務原型,滿足需求,但是在發展的中後期就顯得略有點後勁不足。

因為PHP在高併發、多程序/執行緒以及密集計算領域並不擅長。這種情況在swoole出現之後得到了很大的緩和。

但是,隨著微服務架構的興起以及容器時代的到來,這種情況又再次加劇。因為PHP大都需要藉助Nginx和PHP-FPM或類似軟體來進行程序管理,這對於部署的微服務意味著部署PHP專案程式碼的同時必須同時包括PHP-FPM和Nginx,這除了增加資源成本也降低了效率。

2、Why Golang

那麼,為什麼是Golang呢?

首先,Golang與PHP很像,都是類C語言,可以很好的進行『知識遷移』

其次,Golang在效能和開發效率上有很好的平衡,語法簡單,語言層面上支援併發程式設計,且基礎庫健全,部署容易。

最重要的是,Golang在微服務與容器領域有很好的基礎,後期系統可完美實現微服務化與容器化。

當然了,即便如此,PHP還是世界上最好的語言。

附上一些Go的教程,適合剛入門級別看看,算是福利。關注頭條號,私信回覆“資料”獲取。

淺談從PHP遷移至Golang(基礎篇)

3、How To

做好了思想上的準備之後,就可以開始確立技術方案了。

任何大型系統的重構都不可能是一蹴而就,頃刻之間發生的,需要一個循序漸進的過程。並且,在此重構過程中,大前提必須保持現有系統的所有業務照常執行,所以需要確立的是一個對系統基本無損的分模組逐步替換的方案。

迴歸到我們當前的系統架構:每臺伺服器上均部署相同的PHP專案程式碼,統一由PHP-FPM解釋執行,並透過Nginx進行反向代理。

在梳理了系統各功能模組業務職責之後,我們決定先將資料模組試水:使用Golang進行改造,理由是資料模組功能較為簡單,Golang只需計算邏輯然後向前端頁面提供資料介面即可。同時藉助Nginx的反向代理功能,將資料介面字首的轉發至Golang程式,其他所有請求還是依舊轉發至原來的PHP-FPM程式。其抽象模型大致如下:

淺談從PHP遷移至Golang(基礎篇)

4、About Hot-Update

所謂

熱更新

,是指在系統升級或修復bug過程中對使用者來說是無感知的。

使用PHP開發時,開發者無需關心熱更新,因為PHP是解釋型的程式語言,PHP-FPM會根據最新的請求實時去呼叫執行具體某個PHP檔案;而Golang則不同,它是編譯型語言,在執行時會把Golang檔案載入到記憶體,這時,所有對程式碼的改動想要更新必須要重啟服務才能生效。那麼如何在重啟服務過程中,不影響當前使用者請求,便是熱更新需要解決的問題。

目前Golang熱更新大致有兩個思路:Plugin包(Golang1。8+,原理類似C++動態連結庫方式)和第三方熱更新庫(如)Facebook開源的grace庫以及endless庫等。

關於第三方熱更新庫邏輯大致為:

釋出變更的專案程式碼檔案

傳送變更通知給服務程序(訊號方式,通常是USR2訊號)

服務程序收到通知後,呼叫 fork/exec 啟動最新專案程式碼(新程序)

子程序呼叫會從父程序繼承 socket 檔案描述符來重新監聽 socket(此時父子程序同時Accept連線)

原有父程序不再接收新請求,待正在處理中的請求處理完後,程序自動退出(gracefully shutdown)

子程序託管給init程序

總結

以上大致接介紹了從PHP專案遷移到Golang所需的一些思想與技術上的準備,後續篇章將介紹具體技術方案與實現細節。