1. 程式人生 > >kettle呼叫webservice服務Java:java.lang.OutOfMemoryError: GC overhead limit exceeded

kettle呼叫webservice服務Java:java.lang.OutOfMemoryError: GC overhead limit exceeded

說明:

  1. 背景說明:需要定時同步別的業務系統基於webservice釋出的資料(主表、附表)
  2. 問題緣由:service提供方,主表支援批量查詢,一次可以查詢100條,但是附表只能根據主表的主鍵一條一條的查詢。因此我如果要獲取所有的附表內容就要迴圈訪問服務(約1萬多次)因此會出現Java:java.lang.OutOfMemoryError: GC overhead limit exceeded

解決方法:

總體思路:出現記憶體溢位主要是因為我在一個總job中迴圈了1萬多次webservice,在大job中迴圈呼叫小job(100次訪問)解決問題。

  1. 總體流程圖
  2. 前兩項檢查Web服務是否可用,就不具體展示了,可以參考下面的連結,我也是參考他的部落格做的
    https://blog.csdn.net/a275838263/article/details/51302541
  3. lawCount初始化,執行sql是先清空內容表(我是全量更新),查詢主表確定需要迴圈的次數,把lawCount複製到結果集
  4. 設定迴圈變數,lawCount來自前面的結果集,startIndex(從0開始),endIndex(從100開始)確定需要遍歷的主鍵範圍
    var lawCount=previous_result.getRows();//獲取上一個傳遞的結果
    if (lawCount == null && (lawCount.size()) == 0)
    {
        false;
    }else{
        parent_job.setVariable("lawCount", lawCount.get(0).getNumber("lawCount",0));
    	parent_job.setVariable("startIndex", 0);
        parent_job.setVariable("endIndex", 100);
        true;
    }
    

     

  5. 檢驗startIndex的值,只要startIndex的值<=lawCount,就進入迴圈,呼叫服務
  6. lawID初始化,根據startIndex,endIndex查詢迴圈需要依賴的主鍵,複製到結果集
  7. 呼叫子job,在子job中迴圈訪問webservice,得到資料
  8. 把上一步查到的記錄存到變數中,設定小範圍迴圈變數index,lawSize,以及引數lawID到變數
    var lawList=previous_result.getRows();//獲取上一個傳遞的結果
    debugger;
    if (lawList == null &&(lawList.size()==0))
    {
        false;
    
    }else{
        parent_job.setVariable("lawList", lawList);//ArrayList儲存法律法規記錄變數,以陣列形式儲存入law1,law2
    
        parent_job.setVariable("lawSize", lawList.size());//儲存法律法規的總數量
        parent_job.setVariable("index", 0);//迴圈控制變數
        parent_job.setVariable("lawID",lawList.get(0).getString("LAWID","LAWID"));
        true;
    }
    

     

  9. 檢驗小迴圈(100個迴圈)index的值(從0開始),index小於lawSize(100個lawID)就進入迴圈
  10. 具體的抽取ktr由於業務需求,附表欄位包括主表部分欄位,因此我走了兩條查詢,最後把記錄關聯插入;
    1. 生成記錄:是為了初始化一個常量引數
    2. java程式碼中獲取lawID,並配合生成的記錄加密後,形成服務訪問的驗證字串
    3. 具體的訪問步驟
    4. 將out用json解析
    5. 去除out欄位
    6. 關聯兩個結果集記錄
    7. 插入表格
  11. 遞增index,再次進入檢驗index
    var lawList = parent_job.getVariable("lawList").replace("[","").replace("]","").split(",");
    var lawSize = new Number(parent_job.getVariable("lawSize"));
    var index   = new Number(parent_job.getVariable("index"))+1;
    
    if(index<lawSize){
        parent_job.setVariable("lawID",lawList[index]);
    }
    parent_job.setVariable("index",index);
    
    true;
    

     

  12. 遞增lawID範圍,一次小迴圈後,重置startIndex,endIndex的值
    var lawCount 	 = new Number(parent_job.getVariable("lawCount"));
    var startIndex   = new Number(parent_job.getVariable("startIndex"));
    var endIndex   = new Number(parent_job.getVariable("endIndex"));
    
    if(endIndex<lawCount){
        parent_job.setVariable("startIndex",endIndex);
    	parent_job.setVariable("endIndex",endIndex+100);
    }
    
    true;
    

     

  13. 重新檢驗startIndex的值,直到不通過,跳出迴圈,完成抽取

總結:

  1. 提供方改不動,沒辦法只能迴圈呼叫
  2. 只是自己琢磨的kettle處理方式,我相信一定有更好的處理方式
  3. job應該是相對獨立的模組,結束後就會釋放記憶體??所以不會出現溢位??希望大神解答