如果你是跟著文章一天接著一天實作的讀者,那麼你需要確保你的 :
Anser-Tutorial-Service
使用的是最新的v1.1.1
以上的版本Production Service
使用的是最新的v1.0.4
以上的版本Order Service
使用的是最新的v1.1.3
以上的版本
在分散式系統的設計中,微服務之間的協同工作和交易管理十分的重要,單純地在一個協作器中進行邏輯上的補償並不是足夠的。如何確保在面對應用程式異常或錯誤時,整個系統仍能保持一致性和完整性也是一件重要的事情。
在上一章,我們談及了如何在協作器中開始使用 Anser-Saga 的高可用性元件,並清楚地看到了因為錯誤而留存在儲存媒介的協作器快照。本章,我們將更進一步,探討如何存取這些被中斷的協作器快照,並對他們進行補償。
本章將延續上一章的內容,繼續闡述如何處理已失敗卻被我們備份的協作器快照。
打開 Postman ,讓我們直接對被放入 exit
的協作器進行請求:
因為 exit
的生效, PHP 沒有任何的輸出,就像沒有發生任何錯誤一樣。此時,你可以透過 Redis 連線程式連入 Redis 內(筆者使用
Another Redis Desktop Manager):
將 Value 的內容展開來看,你應該可以在裡面發現 orderId
:
將這個 ID 複製出來,讓我們前往 Product Service 以及 Order Service 進行查詢,你可以看到因為協作器終止無法被補償但依舊存在於資料庫的資料:
Product Service
history
資料表
Order Service
order
資料表
建立一個 {Anser-Tutorial-Service}/compensation_restarter.php
檔案,並鍵入以下內容:
<?php
require_once './init.php';
use SDPMlab\Anser\Orchestration\Saga\Restarter\Restarter;
use Orchestrators\CreateOrderOrchestrator;
$restarter = new Restarter();
$result = $restarter->reStartOrchestratorsByServer(
className: CreateOrderOrchestrator::class,
serverName: 'AnserTutorialService'
);
var_dump($result);
上述程式十分簡單,我們依舊使用了 require_once './init.php';
,在該檔案內初始化了協作器快照所需的儲存媒介。接著,透過實體化 Restarter
類別後,執行 reStartOrchestratorsByServer()
進行協作器的補償。值得注意的是,這裡我們傳入兩個參數控制補償:
className
: 欲補償的目標協作器類別名稱。serverName
: 欲補償的目標伺服器名稱。使用 docker-compose exec app bash
進入到容器內,並透過 php compensation_restarter.php
啟動上述 PHP 程式。順利的話你應該能看到下列內容出現在你的 Command Line 介面:
此時我們再回頭確認 Product Service 以及 Order Service :
成功執行補償的 Product Service
history
資料表
成功執行補償的 Order Service
order
資料表
你會發現我們成功地補償了因為 exit
而被中斷執行的協作器。
serverName
直接進行補償如果你的協作器使用多個伺服器同時提供服務,你也可以直接透過下列程式碼跳過 serverName
的過濾,對所有符合 className
的協作器進行補償:
$restarter = new Restarter();
$result = $restarter->reStartOrchestratorsByClass(
className: CreateOrderOrchestrator::class,
);
本章傳達了如何以 Anser-Saga 高可用性機制,為中斷的協作器建立恢復途徑。我們以 Redis 作為對協作器的快照備份媒介,同時也是 Restarter 所讀取的資料庫。透過 Anser 的高可用性元件,將能夠在協作器因意外中斷後,由斷點處向前進行補償,以保障資料一致性。