Seata-php 入門與下半年展望

語言: CN / TW / HK

通俗地講,Seata-php 是 seata 的 PHP 語言實現,實現了 Java 和 PHP 之間的互通,讓 PHPer 也能使用 seata-php 來實現分散式事務。

Seata是一個非常成熟的分散式事務框架,在 Java 領域是事實上的分散式事務技術標準平臺。Seata 目前正在構建其多語言體系【參考文件1】,整個體系包含了目前常用的五大類語言:Java、Go、Python、Js 和 PHP,目前的態勢是後四種語言都依據 Seata Java 版本構建起對應語言的實現。

除了追求 Seata 多語言體系過程中因為開源價值要求構建 Seata 的 PHP 版本這個原因外,作為構建起 Web 1.0 時代技術基礎 LAMP 架構中的要角,PHP 語言在電商和金融交易場景下依然被廣泛使用,而這些場景對資料一致性要求非常強烈,這是構建 Seata-php 最大的誘因,也是其技術價值所在。

1 Seata 架構與多語言體系

image.png 圖片來自 seata 官網

Seata 總體架構由如下角色構成:<br />事務協調器 Transaction Coordinator<br />簡稱 TC,維護全域性事務和分支事務的狀態,驅動全域性事務提交或者回滾。<br />事務管理器 Transaction Manager<br />簡稱 TM,定義全域性事務的範圍,提交或者回滾全域性事務。<br />資源管理器 Resource Manager<br />簡稱 RM,和分支事務在同一個應用,進行分支事務的註冊,報告分支事務的狀態,驅動分支事務的提交或者回滾。

從 C/S 通訊架構角度來看,TC 是服務端,TM 和 RM 是客戶端。TC 與 TM 以及各個 RM 之間使用 netty 框架進行長連結通訊。具體而言,Seata Java 版本的通訊協議是在四層 TCP 協議之上又定義了一套私有的二進位制雙向通訊協議,通訊框架使用了 netty。其他四種語言只要依據 Seata 的通訊協議標準實現其通訊功能,即可在多語言生態體系內任何語言之間進行通訊和服務呼叫。

三個角色中,TM 和 RM 以 SDK API 形式供上層 APP 呼叫,而 TC 是獨立程序部署,使用任何語言實現都可以。據說懶惰是程式設計師的第一美德,在 Seata Java 已經實現了 Java 版本的 TC 的情況下,多語言體系內其他語言就沒必要再做重複工作,只需要構建其對應語言的 TM 和 RM 的 SDK API 包,與 Seata Java TC 通訊即可。

2 Seata 與 PHP 技術

分散式事務技術是微服務技術體系的一環,構建 Seata PHP 首先需要選擇其微服務技術平臺,Seata-php 目前使用的微服務框架是 hyperf。

PHP 在業界以入門門檻低著稱,目前常用的微服務框架有 laravel 以及在其上構建的 lumen。laravel 框架的最大優點就是其生態豐富,各種元件應有盡有,如果 laravel 可以 Spring 框架類比,lumen 就是 Spring Boot。但其缺點是效能堪憂,例如在普通的 8C 機器上,空跑一個只執行 echo 邏輯的 HTTP 服務,其吞吐量僅有 1k qps。

Hyperf 框架是近年內出現的由國人基於 swoole 開發的一個微服務框架,特點如下:

  • 1 類似於 nginx,hyperf 以多程序形式常駐記憶體,每個程序內都有一個彈性執行緒池,正常情況下 hyperf 收到呼叫請求後,可以保證 1ms 之內分配服務執行緒,而 lumen 的響應時間常在 10ms 左右;
  • 2 因為 hyperf 服務常駐記憶體的特點,其穩定性好,資源利用率當然比以 cgi 機制執行的 lumen 低很多;
  • 3 hyperf 的對請求的處理過程借鑑了 Go 語言機制,其 runtime 層面以非同步方式執行上層的使用者同步呼叫,相比 lumen 其吞吐率高而延遲低,例如在同樣環境下使用 hyperf 實現同樣的 echo HTTP 服務,可以輕鬆達到 60k qps;

除了 hyperf 自身穩定性與高效能外,依賴於 hyperf 服務程序常駐記憶體的特點,TC 可以很方便的對 seata-php 的 RM 發起二階段事務處理,即作為 Server 的 Java TC 對作為 Client 的 PHP 版本的 RM 發起 RPC 回撥。如果使用了 lumen 作為 seata-php 的微服務框架,幾乎不可能實現這個技術點。

3 快速入門 Seata-php

基於 hyperf 微服務框架,seata-php 已經實現了 AT 事務模式,並給出了測試用例。本章節的目的是基於現有實現,讓對 seata-php 這個專案感興趣的同學能夠快速入門 seata-php。

3.1 搭建 PHP 開發環境

使用 hyperf/box 這個工具能夠快速建立開發環境,並且能夠與其他自建開發工具鏈隔離,避免汙染日常的開發環境。

3.1.1 下載 hyperf/box

# Mac
wget https://github.com/hyperf/box/releases/download/v0.0.3/box_php8.1_x86_64_macos -O box
# Linux x86_64
wget https://github.com/hyperf/box/releases/download/v0.0.3/box_php8.1_x86_64_linux -O box
# Linux aarch64
wget https://github.com/hyperf/box/releases/download/v0.0.3/box_php8.1_aarch64_linux -O box

sudo mv ./box /usr/local/bin/box
sudo chmod +x /usr/local/bin/box

# 在 https://github.com/settings/tokens/new 建立 token 後,配置到 box 中
box config set github.access-token <Your Token>

  • 注意:
    • 如果你是 Mac 使用者首次使用的話,需要在“系統偏好設定”->“安全性與隱私”中給 box 工具進行授權
    • 已經測試過,X86 的box,可以在 M1 版本的 Mac 上使用
    • 使用 box 時,建立 github access token 許可權需要repoworkflow

3.1.2 配置 PHP 環境

box 下載好後,繼續下載 php8.0 版本

# 下載 php8.0
box get [email protected]
# 將 box 設定為 php8.0 版本
box config set-php-version 8.0

image.png

3.1.3 下載 composer

# 下載 composer
box get composer

image.png

3.2 執行 Seata-php

環境搭建完畢過後,找一個目錄來存放 seata-php 專案的程式碼。

# 找個地方建立一個目錄
mkdir ./seata

# 進入到目錄內
cd ./seata

# 下載 seata 骨架包
git clone https://github.com/PandaLIU-1111/seata-skeleton

# 下載 seata/seata-php 元件包
git clone [email protected]:seata/seata-php.git

# 進入到 seata骨架包內
cd seata-skeleton

# 執行 composer 更新專案內的元件包
box composer update -o

# 檢視是否與 seata/seata-php 建立軟連線
ls -al vendor/hyperf/ | grep seata

# 檢視命令執行後是否有以下內容
...
seata -> ../../../seata-php/  // 與 seata/seata-php 包建立軟連線
...

# 啟動專案
box php bin/hyperf.php start

image.png<br />至此,即可看到 seata-php 執行成功,在命令列中可以看到 seata-php 客戶端與 seata Java 服務端 TC 的互動報文。

3.3 專案程式碼風格

Seata-php 遵循 PSR-1 程式碼規範【參考文件2】。<br />社群提供了一個類似於 Go 語言 gofmt 一樣的程式碼格式化工具 composer cs-fix,具體使用方式是:

# 格式化某個檔案
composer cs-fix ${FileName}
# 格式化某個目錄
composer cs-fix ${DirName}

3.4 測試用例

目前,seata-php 僅提供了單測用例,放置在專案tests目錄中,可直接通過composer test命令執行這些單測用例。我們近期就會把這些單測用例配置在 github action 上,用於測試每個提交的 pr。

下一步,我們會像 seata-go 一樣補充整合測試用例,並配置在 github action 上用於自動測試專案的每個 pr。

4 下半年規劃

Seata-php 目前已有的工作僅僅是邁出了下半年長征的第一步,尚未達到生產可用的狀態。下半年的整體目標是:

  • 1 事務模式 對齊將於 9 月份釋出的 seata java v1.6.0 的 TCC、AT、SATA 和 XA 模式
  • 2 測試用例 單測覆蓋率達 70% 以上,並實現兩種模式下的 seata java 中已有的整合測試用例的 php 版本
  • 3 程式碼samples 實現兩種模式下的 seata java 中已有的 samples 示例的 php 版本
  • 4 文件建設 構建 API 介面級別的詳細說明文件
  • 5 生產案例 實際生產使用者 3 家以上
  • 6 社群建設 培養 seata committer 5 人以上

上述目標可以理解為 seata-php 社群的 KPI。為達成目的,有可分為“三步走” 的如下執行 Plan。

4.1 釋出一個可用版本

這是第一個階段。我們計劃在國慶節前後釋出釋出第一個 GA 版本,詳細的技術點如下:

  • 1 實現 TM 與 RM

         作為分散式事務的發起方,TM 在與下游的微服務應用在通訊時,能夠在 HTTP 協議與 GRPC 協議中,傳遞事務上下文,下游的服務也可以隨時加入到事務中。
    
  • 2 實現分散式鎖 API

         用於避免業務資料在一階段與二階段之間,由於併發被修改,導致二階段提交、回滾失效。
    
  • 3 實現 TCC 與 AT 模式

         完全實現 TCC 模式。<br />           而 AT 模式依賴於具體的 DB 型別和 DB 版本,我們把 DB 限定為 MySQL v5.7,在此之上支援最基本的 INSERT 與 UPDATE 語句,基本可以完成大部分的實際應用場景覆蓋。
    
  • 4 支援註冊中心

        支援註冊中心的目的,是方便 TM 和 RM 對 TC 進行微服務發現。將會支援 File 與 nacos 兩種服務發現方式。<br />          優先支援 File 服務發現方式。其好處是,在 K8s 環境下,可以通過環境變數或者是掛載 configmap,實現動態配置,不依賴人力變更。<br />          其次支援 nacos 作為註冊中心的服務發現方式。目前,國內的 阿里雲、騰訊雲、華為雲等主流雲廠商都支援 nacos 註冊中心,可以方便廣大使用者進行服務聯通。
    
  • 5 其他

         如 自動化的單元測試,整合測試和專案的 samples。
    

社群已經將第一階段射擊到的所有任務都作為 task 釋出在 seata-php issue 上,可以方便檢視任務負責人,並及時跟蹤專案進度 直接檢視當前的進度。

4.2 技術能力全面對齊

這是半年目標的第二階段。這個階段產出的版本,將會是一個比較完善的版本,能夠覆蓋絕大部分的業務場景,降低開發者在使用 seata-php 的門檻與成本。

關鍵技術點如下:

  • 1 實現 XA 與 SAGA 模式

      除了補齊這兩個模式外,還將繼續完善 AT 模式支援的 SQL ,能夠做到支援大部分的 SQL 語句。
    
  • 2 支援配置中心

         支援配置中心的目的,是方便拉取事務相關的配置。初步計劃支援 File、Nacos、Apollo 三種配置方式。
    
  • 3 支援 gRPC

         計劃於 9 月份釋出的 Seata Java v1.6,將支援 gRPC 通訊方式。seata-php 在第二階段也將支援這一 RPC 調動方式進行事務傳播。
    
  • 4 其他資料庫

        首先支援更多的 MySQL 版本,如 v8.0。並支援 PostgreSQL、OceanBase、Redis 等更多型別的 DB。
    
  • 5 事務異常處理

         提升分散式事務防懸掛的能力,自動處理請求冪等、空提交、空回滾、資源懸掛等事務異常邏輯。
    

第二階段的時間節點的 deadline 大概是在本年 11 月底左右。

4.3 社群建設

前兩個步驟,主要集中在 seata-php 自身的技術能力建設上。到此,seata-php 在技術上可以認為已經成熟。

這兩個步驟的推進,首先依賴於社群自身的健康發展,畢竟開源專案的事情需要社群同學來推進。當下社群由 於雨 同學負責發展壯大,專案總體由 星北 同學來負責推進實施,目前已有程式碼 contributor 4 人。

當然,我們歡迎更多的同學參與到 seata-php 的程式碼建設中來。提交 issue 和 pr 時,建議儘可能詳盡的描述相關細節。比如:

  • 提交 bug issue 時

    • 標題可以寫:bugfix:NotFoundClass Redis with php version is 7.2
    • 內容可以提交 bug 的詳細情況、發生現象的詳細情況、對應的堆疊資訊、預期的情況、以及當前的環境情況、發生的事、修復意見、以及補充的資訊、當前的環境情況等資訊。
  • 提交 pr 時

    • 標題可以寫:Feature: AT mode need to support pgsql
    • 內容可以寫明:這個 Feature 的意義,以及期望的用法,還包括其他相關資訊等。

這一步驟與前兩個步驟相生相伴,同步進行。

5 總結

Seata-php 有 seata java 這個標杆在,初期以推進程式碼進度為主。

作為一個開源專案,seata-php 的開源價值當然是在使用者的生產環境使用起來,而生產使用者也是社群建設的一部分。目前已有兩家使用者願意在其開發測試環境對 seata-php 進行驗證,幫助提升專案的穩定性、易用性和程式碼質量。

為保持專案和社群的健康可持續發展,開源專案的貢獻者,不僅包含 coding 的程式碼貢獻者,還應當包括進行文件貢獻、產品宣傳和品牌推廣等方面的貢獻者,我們將組織社群熱心參與者在各大技術論壇發表部落格,在語音和影片網站以及技術大會上進行技術乾貨以及生產案例的推廣宣傳。歡迎對這些工作感興趣的朋友加入社群釘釘群 44788115,與我們聯絡溝通。

參考文件