如果你是跟著文章一天接著一天實作的讀者,那麼你需要確保你的 :
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 的高可用性元件,將能夠在協作器因意外中斷後,由斷點處向前進行補償,以保障資料一致性。