故障診斷和偵錯秘訣 - AWS Flow Framework 對於爪哇

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

故障診斷和偵錯秘訣

本節說明使 AWS Flow Framework 用 Java 開發工作流程時可能會遇到的一些常見缺陷。本節也會提供一些提示,協助您診斷和偵錯問題。

編譯錯誤

如果您使用 AspectJ 編譯時間縈繞選項,則可能會發生編譯時間錯誤,在這類錯誤中,編譯器找不到針對工作流程和活動所產生的用戶端類別。這類編譯錯誤的可能原因在於 AspectJ 建置器會在編譯期間忽略已產生的用戶端。您可以移除專案中的 AspectJ 功能並重新予以啟用,以修復此問題。請注意,每次工作流程或活動界面變更時,您都需要執行這項作業。有鑑於此問題,建議您改為使用載入時間縈繞選項。如需詳細資訊,請參閱「設定AWS Flow Framework適用於 Java 的」一節。

不明資源故障

當您嘗試對無法使用的資源執行作業時,Amazon SWF 會傳回未知的資源錯誤。此故障的常見原因如下:

  • 您用來設定工作者的網域並不存在。若要修正此問題,請先使用 Amazon SWF 主控台Amazon SWF 服務 API 註冊網域。

  • 您嘗試建立之類型的工作流程執行或活動任務並未註冊。如果您嘗試在執行工作者之前建立工作流程執行,即可能發生此問題。因為工作者會在第一次執行時註冊其類型,所以您必須至少先予以執行一次,再嘗試開始工作流程執行 (或使用主控台或服務 API 手動註冊類型)。請注意,在類型註冊之後,即使未執行任何工作者,您還是可以建立執行。

  • 工作者嘗試完成已逾時的任務。例如,如果 Worker 花費太長時間來處理任務並超過逾時,則在嘗試完成或失敗任務時會出現 UnknownResource 錯誤。 AWS Flow Framework 工作者將繼續輪詢 Amazon SWF 並處理其他任務。不過,您應該考慮調整逾時。調整逾時需要您註冊新版本的活動類型。

對 Promise 呼叫 get() 時發生例外狀況

與 Java Future 不同,Promise 是一種非封鎖建構,對尚未就緒的 Promise 呼叫 get() 將會拋出例外狀況,而非封鎖。使用 a 的正確方法Promise是將其傳遞給異步方法(或任務)並在異步方法中訪問其值。 AWS Flow Framework 對於 Java,只有當傳遞給它的所有Promise參數都準備就緒時,才會調用異步方法。如果您認為您的代碼是正確的,或者在運行其中一個 AWS Flow Framework 示例時遇到此問題,則很可能是由於 AspectJ 未正確配置。如需詳細資訊,請參閱「設定AWS Flow Framework適用於 Java 的」一節。

非確定性工作流程

如「不確定性」一節所述,您工作流程的實作必須具有確定性。可能導致非確定性的一些常見錯誤為使用系統時鐘、使用亂數,以及產生 GUID。因為這些建構可能會在不同的時間傳回不同的值,所以工作流程的控制流程可能會在每次執行時採用不同的路徑 (如需詳細資訊,請參閱「AWS Flow Framework基本概念:分散式執行」和「一探究竟」一節)。如果框架在執行工作流程時偵測到非確定性,即拋出例外狀況。

版本控制所造成的問題

當您實作工作流程或活動的新版本時 (例如,當您新增功能時),您應該使用適當的註釋來增加類型的版本:、或。@Workflow @Activites @Activity在部署新版本的工作流程時,您現有的執行版本通常正在執行。因此,您需要確定具有適當工作流程和活動版本的工作者取得任務。達成此目標的方式是為每個版本使用一組不同的任務清單。例如,您可以在任務清單名稱的後方附加版本編號。如此能確保將屬於不同工作流程和活動版本的任務指派給適當的工作者。

對工作流程執行進行故障診斷和偵錯

疑難排解工作流程執行的第一步是使用 Amazon SWF 主控台查看工作流程歷程記錄。工作流程歷史記錄為一完整與可信賴的記錄,內含變更工作流程執行之執行狀態的所有事件。此歷史記錄由 Amazon SWF 維護,對於診斷問題而言非常寶貴。Amazon SWF 主控台可讓您搜尋工作流程執行,並深入研究個別歷史記錄事件。

AWS Flow Framework 提供可用於在本機重新執行工作流程執行並對其進行除錯的WorkflowReplayer類別。使用這個類別,您可以偵錯已關閉和執行中的工作流程執行。 WorkflowReplayer依賴儲存在 Amazon SWF 中的歷史記錄來執行重播。您可以將其指向 Amazon SWF 帳戶中的工作流程執行,或提供歷史記錄事件 (例如,您可以從 Amazon SWF 擷取歷程記錄並在本機序列化以供日後使用)。當您使用 WorkflowReplayer 重新執行工作流程執行時,不會影響您帳戶中執行的工作流程執行。重新執行完全在用戶端上執行。您可以對工作流程進行偵錯、建立中斷點,並如常使用偵錯工具來逐步執行程式碼。如果您使用的是 Eclipse,請考慮添加步驟過濾器來過濾 AWS Flow Framework 包。

例如,下列程式碼片段可以用來重新執行工作流程執行:

String workflowId = "testWorkflow"; String runId = "<run id>"; Class<HelloWorldImpl> workflowImplementationType = HelloWorldImpl.class; WorkflowExecution workflowExecution = new WorkflowExecution(); workflowExecution.setWorkflowId(workflowId); workflowExecution.setRunId(runId); WorkflowReplayer<HelloWorldImpl> replayer = new WorkflowReplayer<HelloWorldImpl>( swfService, domain, workflowExecution, workflowImplementationType); System.out.println("Beginning workflow replay for " + workflowExecution); Object workflow = replayer.loadWorkflow(); System.out.println("Workflow implementation object:"); System.out.println(workflow); System.out.println("Done workflow replay for " + workflowExecution);

AWS Flow Framework 也可讓您取得工作流程執行的非同步執行緒傾印。此執行緒傾印可將所有開啟之非同步任務的呼叫堆疊提供給您。此資訊可以用來判斷執行中的哪些為待定且可能停擺的任務。例如:

String workflowId = "testWorkflow"; String runId = "<run id>"; Class<HelloWorldImpl> workflowImplementationType = HelloWorldImpl.class; WorkflowExecution workflowExecution = new WorkflowExecution(); workflowExecution.setWorkflowId(workflowId); workflowExecution.setRunId(runId); WorkflowReplayer<HelloWorldImpl> replayer = new WorkflowReplayer<HelloWorldImpl>( swfService, domain, workflowExecution, workflowImplementationType); try { String flowThreadDump = replayer.getAsynchronousThreadDumpAsString(); System.out.println("Workflow asynchronous thread dump:"); System.out.println(flowThreadDump); } catch (WorkflowException e) { System.out.println("No asynchronous thread dump available as workflow has failed: " + e); }

遺失的任務

有時您可能會關機工作者並接著啟動一連串的新工作者,卻發現任務都交付過去給舊的工作者。因為系統中的競爭條件分散到數個程序,所以可能發生這種情況。當您以緊密迴圈執行單位測試時,也可能會出現此問題。而在 Eclipse 中停止測試有時也可能會導致這種情況,因為有可能未呼叫關機處理器。

為了確定問題實際上是由舊工作者取得任務所造成,您應該查看工作流程歷史記錄,判斷哪個程序收到了您預期新工作者應收到的任務。例如,歷史記錄中的 DecisionTaskStarted 事件包含已收到任務的工作流程工作者的身分。Flow Framework 使用的 ID 格式為:{processId}@{host name}。例如,以下是 Amazon SWF 主控台中用於執行範例的DecisionTaskStarted事件詳細資訊:

事件時間戳記

Mon Feb 20 11:52:40 GMT-800 2012

Identity

2276@ip-0A6C1DF5

排程事件 ID

33

為了避免此情況,請為每個測試使用不同的任務清單。另外,請考慮新增關閉舊工作者與啟動新工作者之間的延遲。