3.2 設計原理
3.2.2 Catch-And-Retry 指令設計
國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
3.2.2 Catch-And-Retry 指令設計
在指令的設計上,依據前面一些文獻的探討還有開發經驗與一些測試。這此指令是應用 在網際網路上大規模分散式系統。目標程式語言為 C#。在應用上須滿足幾項情境:
catch exception
補獲故障。這項需求在現代的程式語言多有支援。
retry
重試,重新執行失敗的指令。在 C#未支援要做一些加工。
skip/ignore
忽視例外故障。不重要,不嚴重,影響不大,可承受的故障,如:“按讚”,可 能重試過幾次最終還是失敗,那就忽略掉吧。
restore state
要能恢復運算到半途的不正常狀態。這情境並不算少若能支援就能減少一些恢 復的開發工作。
re-schedule,重新排程。這需要平台支援且可能造成邏輯順序問題,故在 此階段不實作。且指令須有等冪(idempotent)特性才能重新排程。
在語法結構上依文獻探討要有像這樣的五個段落:
Try - Catch - Retry - Fail - Finally
不過真的試著做了後,發現要十個段落才能滿足又好用:
Enter - Try - Catch - Restore - Wait - Recovery - Retry - Fail - Ignore - Leave
這十個段落一一說明如下:
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
Enter,進入點。進入被包裹的程式碼區塊時執行。
Try,即被包裹的程式碼區塊。也就是主功能邏輯程式碼區塊。在 AspectW 就是由 Do 函式負責包裹。
Catch,補獲例外故障。
Restore,還原狀態,當補獲故障後立即還原本地端的應用程式狀態。
Wait,補獲故障後先稍停一小段額定的時間。
Recovery,復原操作,與 Restore 不同的是需自製復原操作程式碼。
Retry,重試,重新執行剛剛失敗的指令並指定重試次數以免無限循環。
Fail,進階操作,若多次 Retry 最終還是失敗可在此決定要如何處理。
Ignore,忽視例外故障。
Leave,離開點,離開被包裹的程式碼區塊時執行。與關鍵字 finally 用意 相同。在命名上為與 Enter 相呼應而改取。
在實作指令時又依使用頻率與情境狀況再次調整,分成五個主要指令型,再依應用 細節有多載(overloading)變型,以下只說明這五個主要指令型:
一、Enter-Leave
指令宣告:OnEnterLeave(Action enterAction, Action leaveAction)
以 event 的型式來對待,在進入被包裹的程式碼時調用 enterAction 離開時調用 leaveAction。
二、Try-Catch-Wait-[Recovery]-Retry
‧
指令宣告:Retry<TException>(int retryDuration, int retryCount) Retry<TException>(int retryDuration, int retryCount ,
Action<TException> recoveryAction , Action<TException> failAction)
這是最主要的指令,因應對多種狀況有多個變型,這裡說明其中的兩個,一個基本 的與一個進階的。基本款假設使用情境是當發生故障時不必特別的處置只須稍停一段額 定時間後再重試就能成功。此情境應該在大部份狀況下都符合。在基本款部份參數只有 兩個,其中 retryDuration 指定當故障後先稍停多少豪秒,然後再重新執行由 Do 包裹 的主功能邏輯程式碼區塊(之後簡稱為:主程式碼)。retryCount 參數限制重試次數上 限。進階款多了二個參數,recoveryAction 指示在重新執行前,先調用以復原狀態後再 重試,而若最終還是失敗就調用 failAction 做處理。預估 failAction 應該很少會用到 不過還是加入設計。
三、Restore
指令宣告:Restore(params RestoreWhenFail[] restoreArgs)
設計來復原本機端的狀態,此機制相當複雜在下面〈章節 3.2.3 Restore 設計原理 說明〉再介紹細節。以應用程式狀態的復原來說,最好的解決方案是用 STM(software transactional memory),不過這項技術並不成熟,故改採比較原始但可信任的機制:
備份與還原。
使用上把想保護的狀態物件當作特製類別 RestoreWhenFail 的建構參數用以備份 (backup),當補獲到故障時會馬上被還原(restore)。
四、Fail
指令宣告:HandleFail(Func<Exception, HandleFailMethod> failHandler)
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
設計來處理進階的狀況,也就是當使用 Retry 指令無法滿足時才派上用場。
先說明參數型別 Func,它與 Action 都可視為 Delegate 差別在它有回傳值而 Action 沒有。以此例子“Func<Exception, HandleFailMethod>”來說,是表示函式特徵(Function Signatures)有一個輸入參數型態是 Exception 且也有回傳值型態是 HandleFailMethod 的函式。比如像下面這樣的故障處理函式:
HandleFailMethod FooFailHandler(Exception ex);
此故障處理函式可能做一些比較特別的復 原動作。不管如何復原,在完成離開前必須回傳 給一個訊息告知 AspectW 這個故障是要
“ThrowOut”向外通告,或是“Retry”重新執 行,或是“Ignore”忽略不管。圖 3.13 說明 HandleFailMethod 的資料結構程式碼。
五、Ignore
指令宣告:Ignore()
Ignore<TException>()
如同其名,設計來忽略故障。也可透過泛型參數指定只忽略特定的例外故障。有時 有些不是很重要的例外故障是可以忽略的。
圖 3.13 指定故障的應對方式
‧
應用程式狀態(application state)的保留與恢復一個另外獨立的研究主題,這個研究 的解決方案以 STM(software transactional memory)為主。STM 已有一些研究成果但還 不成熟。本系統以 C# 程式語言為應用目標,所以以.NET Framework 平台的 STM 研究為 主。試著找了幾天,有看到二個官方的研究案:SXM 與 STM.NET,不過都沒正式釋出。
其中 STM.NET 在.NetFx40 beta 有出試用版,但沒有後續的釋出。現在.NetFx4.5 已釋出 但沒有 STM.NET 功能,查了一些原因原來是因為有人找到了一些嚴重的漏洞所以就被取
一、備份:深層複製(deep clone)一份副本。
二、還原:將副本指定(assign)回來。
這兩件工作看似單純實作起來立馬就發現問題。備份的處理就是複製一份,在想法 上是這麼的直覺,可技術上複製又有分所謂淺層複製與深層複製,在高度物件化的程式 語言,都只做到淺層複製。在尋找多日才找到方法,可以使用序列化(serialization ) 技術來處理。序列化可以理解成就是存檔與讀檔。一般存檔都是存到磁碟機,透過序列 化可以導向記憶體完整地儲存一份副本,在需要還原時再反序列化回來。
還原的部份直覺上也是認為是簡單的,但一開始實作時馬上就遇到一個問題,因為 是必需透過 AspectW 來復原所以必需取得狀態物件的指標才行,這問題就來了因為 C# 這