批處理最佳實踐 - Vlad Mihalcea
大多數應用程式至少具有一個批處理任務,在後臺執行特定的邏輯。編寫批處理作業並不複雜,但是您需要了解一些基本規則,這裡將列舉一些我發現最重要的規則。
從輸入型別的角度來看,處理專案可以透過輪詢資料庫來實現,也可以將資料透過佇列推送到系統中來實現。下面顯示了典型批處理系統的三個主要元件:
- 輸入元件(透過輪詢或從輸入佇列載入資料專案)
- 處理器:主要業務處理邏輯元件
- 輸出元件:輸出結果的輸出通道或儲存位置
分批輪詢
您一次只能檢索一批資料專案。我最近在嘗試檢索所有可能的資料專案進行處理時,排程作業丟擲了OutOfMemoryError。
系統整合測試使用的是少量資料,因此容易透過,但是由於某些部署問題,當計劃排程的作業離線兩天時,由於沒有被觸發使用,因此要處理的資料專案數會大量累積。 ,並且當排程程式重新聯機時,由於資料太大,不適合排程程式的記憶體堆,因此也無法執行。因此,僅設定高的排程頻率還是不夠的。
為避免這種情況,您只需要獲取一批資料,將它們處理消費掉即可,然後您可以重新執行該過程,直到沒有剩餘要處理的東西為止。
編寫執行緒安全的批處理程式
通常,無論您選擇並行執行多少個作業,計劃排程作業都應正確執行。因此,批處理處理器應該是無狀態的,使用本地作業執行的上下文將資料狀態從一個元件傳遞到另一個元件。畢竟,即使是安全的全域性變數也不是那麼安全,因為作業的資料可能在併發執行時混合在一起。
節流
使用佇列時(輸入或在批處理程式中),您應該始終有一個限制策略。如果物品的生產率始終高於被消費的資料量,那麼您將遭受災難。如果排隊的資料專案保留在記憶體中,最終將消耗完記憶體。如果專案儲存在持久佇列中,則佇列空間將用完。因此,您需要一種平衡生產者和消費者的機制。要確保有合適的消費者數量來平衡生產資料。(可透過reactive的背壓)
當佇列大小超過給定閾值時,自動擴充套件消費者就像啟動一個新消費者一樣,是一種合適的自適應策略。當佇列大小低於其他閾值時殺死使用者,可以釋放不必要的空閒執行緒。
create-new-consumer閾值應大於kill-idle閾值,因為如果它們相等,則當佇列大小在閾值大小附近波動時,您將獲得create-kill抖動。
儲存工作結果
只將工作結果儲存在記憶體中是不好的選擇,選擇一個永續性儲存(MongoDB限制的集合)是一個更好的選擇。
如果結果儲存在記憶體中,而不限制一個上限,則批處理處理器最終將耗盡記憶體。重新啟動計劃程式將清除您以前的工作結果,這是非常有價值的處理結果,因為這是您獲得的唯一反饋。
瘋狂的外部服務提供商
for(GeocodeRequest geocodeRequest : batchRequests) { mapsService.resolveLocation(geocodeRequest); } |
這段迴圈程式碼會瘋狂呼叫您的地圖服務提供商,這給他們的伺服器帶來了很大壓力。如果這樣批處理請求數很高,那麼您可能會被禁止訪問。
您應該在兩次請求之間新增一個短暫的延遲,但是不要讓您的當前睡眠中斷,而應使用EIP延遲器。
對批處理程式使用EIP樣式程式設計
儘管程式風格的程式設計是大多數程式設計師的預設心態,但許多批處理任務更適合企業整合模式設計。所有上述規則都可以使用EIP工具輕鬆實現,例如:
- 訊息佇列
- 投票渠道
- 變形金剛
- 分離器/聚合器
- 延遲器
結論
使用EIP元件可以簡化測試,因為您一次只專注於一項職責。EIP元件透過佇列傳遞的訊息進行通訊,因此將一個同步處理通道更改為排程的執行緒池只是一個配置細節。
有關EIP的更多資訊,請檢視出色的Spring Integration框架。我已經使用了三年了,接受其強迫性以後,您將更喜歡它而不是過程程式設計。
相關:
相關文章
- 使用 Spring Transactional 註釋的最佳方式 - Vlad MihalceaSpring
- 使用JPA和Hibernate延遲載入實體屬性的最佳方法 - Vlad Mihalcea
- 使用JPA和Hibernate呼叫儲存過程的最佳方法 - Vlad Mihalcea儲存過程
- 適合用於資料庫主鍵的最佳UUID工具庫 - Vlad Mihalcea資料庫UI
- Spring Boot 之 Spring Batch 批處理實踐Spring BootBAT
- 自然語言處理的最佳實踐自然語言處理
- 20個異常處理的最佳實踐
- Java中的異常處理最佳實踐Java
- 如何啟用Hibernate慢查詢日誌? -Vlad Mihalcea
- SQL 搜尋方法或鍵集分頁 - Vlad MihalceaSQL
- 處理Java異常的9個最佳實踐Java
- Java異常處理的9個最佳實踐Java
- Spring Boot統一異常處理最佳實踐Spring Boot
- 處理Java異常的10個最佳實踐Java
- redis自學(47)批處理最佳化Redis
- JDBC驅動程式Maven依賴項大全列表 - Vlad MihalceaJDBCMaven
- 什麼是單主資料庫複製? -Vlad Mihalcea資料庫
- Java異常處理最佳實踐及陷阱防範Java
- Flink 在又拍雲日誌批處理中的實踐
- 簡單實現批處理
- Node.js 服務連線 MongoDB 處理最佳實踐Node.jsMongoDB
- 批處理概述
- 2PL(兩階段鎖定)演算法如何工作 -Vlad Mihalcea演算法
- COBOL六十週年紀念:過去,現在和未來 -Vlad Mihalcea
- 使用DataSource-Proxy在Spring Boot中記錄SQL語句 - Vlad MihalceaSpring BootSQL
- 理解RESTful:理論與最佳實踐REST
- 在JPA中請優先使用sequence策略生成實體識別符號的值 - Vlad Mihalcea符號
- 使用FlexyPool度量你的XA事務連線池合適大小 - Vlad MihalceaFlex
- [Docker]寫 Dockerfile 的最佳實踐理論Docker
- Java中處理異常的9個最佳實踐,你必須要知道!Java
- Apache Beam,批處理和流式處理的融合!Apache
- 使用無伺服器實現檔案處理的批處理 - DZone Cloud伺服器Cloud
- 什麼是批處理
- Dynamics CRM 2013 批處理
- bat 批處理字串操作BAT字串
- window 批處理檔案
- Spark SQL:實現日誌離線批處理SparkSQL
- 如何通過隧道將本地主機連線到公共網際網路上 - Vlad Mihalcea