以下就分成幾個部分來說明這兩個概念:
GridTask & GridJob Interfaces
由於分散式運算所需注意的地方很多,因此 GridGain 將應該要有的功能清楚的定義在 GridTask 與 GridJob 兩個 interface 中,讓使用者可以知道如何建立一個 Grid Task,然後對其進行後續的操作。
在第一篇提到,Grid Task 即是使用者送出的工作,而 GridGain 在 GridTask interface 中定義了幾個功能,分別是:
- 將使用者派送的工作,根據自訂的規則拆成(split)多個 Grid Job
- 接收 remote grid node 處理 Grid Job 的結果
- 將所有的處理結果進行彙整(reduce)
而若要建立 Grid Task,必須實作 GridTask interface,其中當 GridTask.map(List, T) method 被呼叫時,就可以取得由該 Grid Task 所拆開的 Grid Jobs 的資訊(會被派送到那個 grid node 去執行的相關訊息),再由 GridGain 將 Grid Job 序列化(serialize)傳送至 remote grid node 執行。
Grid Task Execution Sequence
這個部分要說明 Grid Task 執行的步驟細節:
- 接收到 grid task 的執行要求,並根據使用者給定的名稱,準備開始將 grid task 部署到 Grid 上。
- Grid 將會產生與此 grid task 相對應的 session 資訊。
- Grid 會根據使用者在程式中所加入的 annotation,注入(inject)所需要的 resource 到 grid task instance 上。
- 接著 Grid 會呼叫 GridTask.map(List, T) method,將 Grid Task 拆成多個 Grid Jobs 之後,再取得 Grid Job 與 remote grid node 對應的相關執行時的資訊。
- 有了 Grid Job 與 remote grid node 的對應資訊後,就可以開始將 job 丟到 remote grid node 上去執行。
- 當 job 傳到 node 準備執行前,會根據使用者在 GridCollisionSpi SPI 中所設定的方式進行處理,有可能會有以下三項:
- WAIT:job 會進入 waiting list,等待有新 job 到達或是先前 job 已經處理完後,才會被移到 active list 中開始執行(此時 Collision SPI 會被呼叫,job 才會有所動作)。
- EXECUTE:job 會直接被移到 active list 中執行。
- REJECT:如果目前 active list 中有 job 正在執行,則此 job 會被拒絕執行;此時會將包含有 GridExecutionRejectedException 例外的 GridJobResult instance 傳入 GridTask.result(GridJobResult, List<GridJobResult>) 作為參數。
- WAIT:job 會進入 waiting list,等待有新 job 到達或是先前 job 已經處理完後,才會被移到 active list 中開始執行(此時 Collision SPI 會被呼叫,job 才會有所動作)。
- 對於位於 node active list 中的 job,Grid 會將使用者指定的所有 annotation resource 注入(inject)到 Grid Job instance 中。
- remote grid node 會執行使用者在 GridJob.execute() 中所實作的工作。
- 當 job 在遠端執行完成後,會將結果回傳至 Grid Task,並傳入 GridTask.result(GridJobResult, List<GridJobResult>) 作為參數;若執行期間有例外產生,在可檢查到的例外發生情況下,可透過 GridJobResult.getException() 取得例外資訊;若無法檢查到的例外,會被統一包裝為 GridUserUndeclaredException 例外。
- 每個 job 執行完都會呼叫一次 GridTask.result(GridJobResult, List<GridJobResult>) method,此 method 會回傳 GridJobResultPolicy instance,而 Grid 會根據所回傳的 policy instance 來決定後續的 job 的處理方式,可以有以下三種作法:
- GridJobResultPolicy.WAIT:Grid Task 會持續等待其他工作的完成,直到最後一個工作完成後,會呼叫 GridTask.reduce(List) method 將結果彙整。
- GridJobResultPolicy.REDUCE:當收到的 policy 為 REDUCE,則會馬上呼叫 GridTask.reduce(List) method 進行結果的彙整,而其他未完成的 job 則會收到 cancel 的命令。
- GridJobResultPolicy.FAILOVER:job 在執行中若是發生錯誤時,就會收到 FAILOVER policy;此時會根據使用者在 GridFailoverSpi 中的實作來決定要將 job 傳到何處繼續執行(若使用的是 Grid Task Adapter,則在發生 node crash 或是 job rejection 時,就會自動將 job 派送到其他 node 繼續執行)。
- GridJobResultPolicy.WAIT:Grid Task 會持續等待其他工作的完成,直到最後一個工作完成後,會呼叫 GridTask.reduce(List) method 將結果彙整。
- 當所有 job 都處理完,也都收到回傳結果後,就會呼叫 GridTask.reduce(List) method 將結果彙整。
- 最後 Grid 會將相關的 session resource 全部清除,包含 attribute、checkpoint .... 等等,此時表示 Grid Task 正式執行完畢。
還有一點需要注意的! 當 job 在 remote grid node 執行到一半時收到中斷執行(cancel)的命令時,GridJob.cancel() method 就會被呼叫;使用者可以在此 method 進行實作,可以決定讓 job 忽略中斷繼續執行、直接中斷,或是進行其他不同的工作 .... 等等。
而通常 job 會再執行到一半被中斷的原因,有可能會有以下幾種:
- Collision SPI 中斷了正在執行的 job。
- Grid Task 已經執行完畢,而不需要再繼續等待其他 job 執行回傳的結果。
- 使用者呼叫了 GridTaskFuture.cancel() method 停止整個 Grid Task 繼續執行。
Resource Injection
在 GridTask 與 GridJob 之間訊息的傳遞,或是控制資訊的交換,在 GridGain 中通稱為 Grid Resource。
而 GridGain 使用 IoC(Inverse of Control) 的方式,讓使用者可以透過 annotation 的方式將 resource 注入(inject),而 annotation 可以用在 field 上,也可以用在 method 上喔!!
以下介紹幾個常用的 Grid Resource:
Grid Resource | 描述 |
GridTaskSessionResource | 此即為上一篇所提到的 Distributed Grid Task Session(可以根據需求自訂 resource 為 primitive type 或是 object) |
GridInstanceResource | 正在執行的 task 所屬的 Grid instance |
GridLoggerResource | GridLogger instance,而此 Logger instance 將會被 Grid instance 所使用 |
GridHomeResource | GridGain 安裝目錄的資訊 |
GridExecutorServiceResource | java.util.concurrent.ExecutorService instance (供 Grid 所使用) |
GridLocalNodeIdResource | 本地端 Grid Node ID,型態為 java.util.UUID |
GridMBeanServerResource | javax.management.MBeanServer instance (供 Grid 所使用) |
GridJobIdResource | 代表 Grid Job 的唯一 ID 值,型態為 java.util.UUID |
在 GridGain 中定義的 Grid Resource 一共就是以上這八種,詳細的使用方式可以參考官方網站的說明。
Convenience Adapters
之前介紹的 Grid Task、Grid Job、Grid Resource .... 等等不同的部分,要瞭解這些部分才能順利的開發程式,其實有蠻多細節是必須要注意的! 實際學習上也不是這麼容易!
因此 GrinGain 中提供了幾個 adapter,可以讓使用者在程式開發上更容易上手喔!!
以下來介紹這些 adapter:
Adapter | 描述 |
GridTaskAdapter | GridTaskAdapter 提供了預設的 GridTask.result(GridJobResult, List<GridJobResult>) 實作,當 remote grid node 在執行工作時發生 node crash(拋出 GridTopologyException 例外) 或是 job 被拒絕執行(拋出 GridExecutionRejectException 例外)時,會自動處理 Job Failover 的工作。 |
GridTaskSplitAdapter | GridTaskAdapter 提供了讓使用者透過自行實作 GridTaskSplitAdapter.split(int, T) method 的方式,讓使用者可以根據需求決定要如何將 Grid Task 拆成 Grid Jobs,隱藏了 job 與 node 的配對相關資訊,讓整個工作更為簡化。 |
GridJobAdapter | GridJobAdapter 提供了預設沒有實作內容的 GridJob.cancel(),因此若無此需求,使用者可以不用再實作此 method;並允許使用者根據需求取得或設定 job 的參數。 |
GridGain 提供的 Adapter 不只以上這三種,若想要更瞭解 Adapter 的相關細節,可以參考官方網站的文件。
Distributed Session Attributes and Checkpoints
這個部分其實在上一篇都有說明到了! 重點再說明一次:
在 Session Attributes 的部分,藉由設定 session attributes 的方式可以讓 Grid Task 與 Grid Jobs 之間,或是 Grid Sibling Jobs 之間作溝通。
有了這個機制之後,工作較快執行結束的 node,可以根據 session attributes 的值,等待其他 node 將工作處理完畢,因此可以達到一定程度的工作執行流程控制。
另外在 Checkpoints 的部分,則是持續不斷的儲存 job 的執行期間的相關資訊,以便錯誤發生時,可以將此 job failover 到其他的 node 繼續執行,而不需要全部從頭開始。
而這個功能,對於長時間執行的工作來說,是特別的重要的!
沒有留言:
張貼留言