最近把 MixPHP 逐步重構到了 V3 版本,之前停更了很長時間,是因為一直在開發 MixGo ,回想起 V2~V2.2 版本中我做了很多嘗試,其中特別是 V2.2 我非常激進的直接 all in 單執行緒協程,當時我是這樣想的:MixPHP V2.1 為何從 Reactor+Manager+Worker 多程式改為單執行緒協程,但是切換後實際上帶來了一些問題:
- 很多使用者用了一些奇奇怪怪的第3方庫,都是依賴 guzzle 和 curl 的,不管是 swoole hook curl 還是 mix/guzzle hook,總是偶爾出現請求失敗,不穩定的情況,最後無奈只能用同步執行器處理。
- 處理複雜一些的 cli 後臺計算的時候,通道死鎖問題比較嚴重,問題應該是 db pool 丟擲的連線被使用者一直持有,導致死鎖,這個是我 db 封裝的設計沒有考慮好這種情況。
當然上面也都不是解決不了的問題,後面大家也都解決了,只是帶來了一些本不必要的麻煩,總體感受是其實多程式還是有多程式的意義,少了很多不必要的煩惱,很多人表示懷念以前的 v1.1 的多程式同步模式,比如:關閉協程用同步模式的話,就相容 composer 的全部生態,以上煩惱都沒有,效能其實也不差。
太過理想化
在最初開始設計 V2.2 時,其實我太理想主義了,我內心真的是想複製一個 php 版 golang 的,我自己開發了 mix/runtime 裡面包含 Select 用來處理多通道,風格完全與 Go 類似的 Context,Signal、Time 等基礎庫,但是實際使用時,由於 Swoole 和 Golang 的協程切換機制不同,導致死鎖的問題非常容易出現,最後無奈放棄了,當然我是做非常複雜的那種後臺計算類的需求,如果只是 http 開發 CURD 基本不會遇到。Swoole 還是在 API、WebSocket 等領域比較合適。
微服務
在 V2.2 後期,我做了很多微服務的嘗試,我開發了一個非常好用的 PHP gPRC 伺服器開發庫,我還把整個框架都接入到了 go-micro v1,v2 的生態中,幾乎能使用 micro 全部的工具鏈,尷尬的是後來他們表示 v3 版本將全面 all in 雲微服務。
再到後面我接觸 APISIX 等閘道器產品後,我感覺其實我們程式設計師就直接寫 gRPC 和 http 這些介面就可以了,服務少的時候用 ALI 的內網 SLB 簡單手動的註冊一下負載均衡,多的時候就直接啟動一個 APISIX 這種閘道器,然後把 host 切換到閘道器地址就可以了,其他的服務發現、熔斷、鏈路啥的都不用去硬編碼到框架裡了,反而簡單高效,當然發現其實還是要去呼叫閘道器介面的,但是相比之前我全部用程式碼+etcd去處理要單純很多。
完全獨立的模組
以前我開發框架是先構建整體,然後根據框架的需要拆分模組,這導致了模組太多了,有些程式碼老是感覺放哪裡都不太對非常的糾結,各個庫之間總是有千絲萬縷的聯絡,獨立使用的時候老是連帶下載一堆的庫。
V3 開始我採用了完全 golang 的那種可插拔的封裝思想,我先開發很多個獨立的庫,這些庫的程式碼儘量的內聚,然後我編寫一個骨架,將這些庫組合起來使用,我逐步的重構了這些最重要的庫。
- mix/vega PHP 編寫的 CLI 模式 HTTP 網路框架,支援 Swoole、WorkerMan,與 Go 生態的 gin 定位一致
- mix/database 可在各種環境中使用的輕量資料庫,支援 FPM、CLI、Swoole、WorkerMan,可選的連線池 (協程)
- mix/redis 可在各種環境中使用的 PHP Redis,支援 FPM、CLI、Swoole、WorkerMan,可選的連線池 (協程)
- mix/redis-subscribe 基於 Swoole 協程的 Redis 原生協議訂閱庫
- mix/grpc 基於 Swoole 協程的 PHP gRPC 庫,包含 protoc 程式碼生成器、伺服器、客戶端
- mix/websocket 基於 Swoole 協程的 PHP WebSocket 伺服器與客戶端
- mix/validate 基於 PSR-7 的驗證庫
- mix/worker-pool 基於 Swoole 的協程池、工作池庫
- mix/event 基於 PSR-14 標準的事件排程庫
- mix/cli PHP 命令列互動指揮官
重構中
每個庫都是獨立可執行的,你可以只使用 mix/vega 來搭配 laravel orm 使用;可以在任意環境中使用 mix/database 和 mix/redis;可以使用 mix/grpc 原生程式碼編寫 gRPC;所有的模組你可以像搭積木一樣隨意組合。
更多的使用場景,暴露原生介面
在 V1,V2 的時候,我們總是隻能在一種固定的程式模式下使用,因為我們這些框架把 swoole 底層封裝起來了,因為封裝導致原生介面其實是無法暴露出來的,因此都是透過配置的方式來做一些有限的模式切換。
V3 我做的比較徹底,我透過封裝的 mix/vega 只在請求事件那裡引入框架,完全把原生程式碼暴露出來,帶來了非常靈活的啟動方式,可以同時支援:Swoole 多程式同步,多程式協程,單程式協程,WorkerMan 多程式同步。包含了 CLI 下兩大生態的全部執行模式,並且程式碼完全一致,可以隨意切換,這帶來了巨大的可選擇性,對協程相容性困擾的使用者可以選擇同步模式,在 windows 下無法開發的使用者可以選擇 workerman 驅動,甚至如果需要 Swow、FPM 我都可以接入進來 [已經接入FPM]。
資料庫元件
這次資料庫解決了之前的持有連線導致死鎖的問題,同時最佳化了池的實現,同時廢棄了之前複雜的 where 設計,採用的更加簡單的 ? 繫結方式,這種方式在 golang 中普通採用。這些改變帶來了穩定性和效能的提升,同時更加雅觀了,當然還增加了 FPM 的支援,我看到有些使用者喜歡單獨使用他們。
資料庫不管在協程、同步、FPM 執行,程式碼無需修改,只有在協程時單獨呼叫一下 startPool()
即可。
獨立、靈活、效能好
以上,MixPHP V3 帶來了很多顯著的變化,但依然是一個輕量的高效能框架,現在你可以像使用 symfony
一樣獨立使用我們的模組了。
本作品採用《CC 協議》,轉載必須註明作者和本文連結