大型批次管道的最佳做法

本文說明如何盡量減少大型批次管道作業失敗的影響。大型工作負載失敗的影響特別嚴重,因為從這些失敗中復原及修正需要時間和金錢。如果這些管道失敗,從頭重試會耗費大量時間和金錢。

如要減少成本高昂的批次管道失敗次數,請按照本頁的指南操作。 由於您無法完全避免元素和管道失敗,因此我們提供的技術著重於提高復原能力、降低失敗成本,以及在發生失敗時,更輕鬆地進行偵錯及瞭解失敗原因。

如需一般管道最佳做法,請參閱 Dataflow 管道最佳做法

針對大型作業執行小型實驗

執行大型批次工作前,請先對資料集子集執行一或多個較小的工作。這項技術可提供成本估算,並協助找出潛在的故障點。

預估費用

執行實驗可預估執行作業的總費用底價。工作費用通常是依 cost of test job*size(full dataset)/size(test dataset) 計算。視管道而定,費用可能會超線性擴展,或較少見的次線性擴展。不過,這個步驟通常能提供工作費用的粗略估算值。你也可以嘗試不同大小的輸入內容,更準確地估算費用規模。您可以根據這項資訊,決定是否要繼續使用現有管道,或是重新設計管道架構來降低成本。

找出故障點

執行實驗可找出錯誤、潛在故障點,或潛在的設定和效率問題。您也可以檢查其他管道指標,例如下列指標:

  • 如果管道幾乎用盡所有可用記憶體,在高負載或記錄特別大的情況下,可能會發生記憶體不足 (OOM) 例外狀況。您可能需要為最終工作佈建更多記憶體,以免發生這些 OOM 錯誤。
  • 如果管道的輸送量下降,請檢查管道記錄,找出原因。您可能會發現卡住的元素,或是資料集的部分內容表現特別不佳。您可以分別處理這些資料點,也可以在處理元素時強制執行逾時。詳情請參閱本文件的「為昂貴的記錄設定逾時」一節。
  • 如果管道在 Dataflow 上的工作執行成效遠不如在本機,請檢查管道邏輯,找出原因。舉例來說,如果您在 Dataflow 上使用八個核心,獲得的輸送量與在本機使用一個核心時相同,則工作可能會因資源爭用而受到瓶頸限制。如果成效不如預期,請考慮採取下列一或多個做法:
    • 使用不同的機器或軟體設定執行更多實驗。
    • 同時使用多個核心在本機進行測試。
    • 檢查程式碼,找出大規模部署時的潛在瓶頸。

如果管道有任何 Dataflow 建議,請按照建議提升效能。

使用無效信件佇列處理非預期的錯誤資料

管道通常會在大多數輸入元素上成功執行,但會在少數輸入元素上失敗。執行小型實驗時,您可能不會發現這個問題,因為這些實驗只會測試部分輸入內容。根據預設,Dataflow 會在批次模式下重試這些失敗的工作四次,在串流模式下則沒有次數限制。在批次模式下,達到重試次數上限後,整個工作就會失敗。在串流模式下,工作可能會無限期停滯。

在許多工作中,您可以使用死信佇列 (未處理的訊息佇列),將這些失敗的元素從管道中排除,並完成其餘工作。死信佇列會將失敗的記錄傳遞至另一個輸出內容 PCollection,您可以與主要輸出內容分開管理。您可透過這項設定為這些記錄設計政策。舉例來說,您可以手動將這些記錄寫入 Pub/Sub、檢查並清除記錄,然後重新處理記錄。

許多 Apache Beam 轉換指令都內建支援無法傳送的郵件佇列。在 Java 中,您可以使用 ErrorHandler 物件存取這些欄位。在 Python 中,您可以使用 with_exception_handling 方法存取這些屬性。部分轉換作業有自訂的無效信件佇列定義方式,詳情請參閱轉換作業的說明文件。詳情請參閱「使用死信佇列處理錯誤」。

如要判斷工作是否符合死信佇列的條件,請參閱本文的「限制」一節。

無效信件佇列限制

在下列情況下,死信佇列可能沒有幫助:

  • 完整工作者或 DoFn 生命週期失敗。如果整個工作站或套件的處理作業失敗,無法透過死信佇列擷取失敗。舉例來說,如果管道遇到記憶體不足 (OOM) 例外狀況,系統會重試 VM 上的所有現有工作,但不會將任何內容傳送至死信佇列。
  • 合併或其他彙整作業。如果管道執行的運算需要所有輸入元素都存在,並做為結果的一部分處理,請務必謹慎使用這個步驟之前的死信佇列。使用無效信件佇列會導致部分輸入資料未納入結果。新增無法傳送訊息佇列可能會以容錯能力換取正確性。
  • 死信佇列路徑發生失敗。如果元素在傳送至無法傳送郵件佇列接收器時失敗,整個管道可能會失敗。為避免發生這種失敗情形,請盡可能保持死信佇列邏輯簡單。您可以新增等待步驟 (請參閱 wait class),確保主要輸入內容完成後,再寫入無法傳送的訊息佇列元素。這項設定可能會降低效能,並延遲管道傳送的錯誤信號。
  • 部分轉換的元素。如果在管道中途插入無效信件佇列,無效信件佇列可能會輸出部分轉換的元素,且無法存取原始元素。因此您無法清除元素,也無法對元素重新執行管道。您可能需要套用不同的邏輯,將無效信件佇列中的輸出內容與原始元素建立關聯,或是解讀及處理部分轉換的元素。也可能導致結果不一致。舉例來說,如果元素會沿著管道的兩個分支傳送,且每個分支都會將導致例外狀況的元素傳送至無法傳送的郵件佇列,則單一輸入元素可能會沿著其中一個、另一個、兩個或兩個分支都不會傳送。

昂貴記錄逾時

處理一小部分較昂貴的元素,或達到導致無回應的限制 (例如死結) 時,管道可能會停止回應。為減輕這個問題的影響,部分轉換作業可讓您設定逾時時間,並在任何使用者程式碼 DoFn 遇到這個問題時,讓逾時的元素失敗。舉例來說,您可以使用 Python 的 with_exception_handling 方法。搭配使用逾時和無效信件佇列時,管道可以繼續處理狀況良好的元素並推進進度,您也可以另外重新處理耗費資源的元素。這項設定可能會導致效能降低。

如要判斷哪些 DoFn 作業可能需要逾時,請先執行小型實驗,再啟動完整管道。

啟用垂直自動調度資源功能

如果您不確定工作需要多少記憶體,或認為工作有記憶體不足的風險,請啟用垂直自動調度功能。這項功能有助於避免管道大規模執行時發生 OOM 失敗,或遇到異常龐大的元素。

由於垂直自動調度功能可能會增加工作成本,且無法避免所有記憶體不足的失敗情況,您仍需解決記憶體用量過多的問題。自動垂直調度資源功能也需要 Dataflow Prime,而這項服務有額外限制,且計費模式不同

使用推測執行來避免落後者

如果是批次管道,您可以啟用推測執行功能,減少執行緩慢或停滯的工作造成的影響。這些緩慢或停滯的作業也稱為落後作業。這項功能會啟動冗餘或備份的作業執行程序,以處理耗時過長的工作。系統會使用先完成的作業,並取消其他作業,藉此縮短管道的整體完成時間。

如果工作項目因工作人員機器速度緩慢,或非決定性錯誤、資源節流或連線問題等暫時性問題而延遲,推測執行功能可提供替代執行路徑,協助管道更快完成作業。

限制和注意事項

啟用推測執行前,請先考量以下事項:

  • 串流管道:串流管道不支援推測執行。
  • 費用可能變動:由於很難預測落後者和備份工作佈建,因此難以估算這項功能對費用的影響。舉例來說,備份工作項目會耗用額外資源,可能導致成本增加,但如果能提早完成,反而可以節省資源並降低成本。無論是哪種情況,預期整體影響都不大。
  • 持續長時間執行的工作項目:如果工作項目持續長時間執行 (例如熱鍵),推測執行可能無法大幅改善效能,因為造成緩慢的根本問題仍會存在。

如要進一步瞭解批次工作中的進度落後項目,請參閱「排解批次工作中的進度落後項目」。

啟用推測執行

如要啟用推測執行,請使用 map_task_backup_mode Dataflow 服務選項。有兩種模式可供選擇:

Java

  • --dataflowServiceOptions=map_task_backup_mode=ON
  • --dataflowServiceOptions=map_task_backup_mode=CAUTIOUS

Python / Go

  • --dataflow_service_options=map_task_backup_mode=ON
  • --dataflow_service_options=map_task_backup_mode=CAUTIOUS

ON 模式中,如果原始工作預計執行時間比新工作預計執行時間長約 20%,系統就會排定備份工作。

CAUTIOUS 模式下,如果原始工作預計執行時間比新工作預計執行時間長約 70%,系統就會排定備份工作。

如要確認推測執行功能已啟用,請檢查記錄訊息。尋找顯示備份工作已啟動的項目。這可確認系統已觸發推測執行。如要查看這些記錄,請前往管道的「Job Logs」(工作記錄) 面板 (依序點選「Jobs」> 選擇工作 >「Logs」部分 >「Job logs」)。記錄訊息如下所示:

Backup issued in step STEP_NAME. ADDITIONAL_INFORMATION.

容易失敗的管道替代方案

部分管道特別容易發生錯誤。雖然最好是解決這些錯誤的來源,但如要降低失敗成本,請考慮下列選項。

具體化中繼結果

管道可能有一或多個特別耗費資源的轉換作業,導致管道執行時間過長。這個轉換作業完成後,如果管道發生故障,可能會造成嚴重損害,因為所有已完成的工作都會遺失。為避免發生這種情況,建議將耗費大量資源的步驟產生的中繼 PCollections 寫入 Cloud Storage 等接收器。這項設定可降低故障成本。您需要權衡這項優勢與執行額外寫入作業的成本。您可以使用下列任一方式,運用具體化結果:

  1. 將原始管道分割為兩個管道:一個管道用於寫入中繼結果,另一個管道用於讀取中繼結果。
  2. 只有在管道失敗時,才讀取並平坦化原始來源和具體化中繼集合的結果。

為確保這些具體化項目在進一步處理前已寫入,請在後續處理步驟前新增等待步驟 (請參閱 wait class)。