從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還是世界上最好的語言。

3、How To

做好了思想上的準備之後,就可以開始確立技術方案了。
任何大型系統的重構都不可能是一蹴而就,頃刻之間發生的,需要一個循序漸進的過程。並且,在此重構過程中,大前提必須保持現有系統的所有業務照常運行,所以需要確立的是一個對系統基本無損的分模塊逐步替換的方案。
迴歸到我們當前的系統架構:每臺服務器上均部署相同的PHP項目代碼,統一由PHP-FPM解釋執行,並通過Nginx進行反向代理。
在梳理了系統各功能模塊業務職責之後,我們決定先將數據模塊試水:使用Golang進行改造,理由是數據模塊功能較爲簡單,Golang只需計算邏輯然後向前端頁面提供數據接口即可。同時藉助Nginx的反向代理功能,將數據接口前綴的轉發至Golang程序,其他所有請求還是依舊轉發至原來的PHP-FPM程序。其抽象模型大致如下:
圖片描述

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所需的一些思想與技術上的準備,後續篇章將介紹具體技術方案與實現細節。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章