天天看點

使用MaxCompute Java SDK 執行任務卡住了,怎麼辦?

場景一

使用者A

A: “親,用 MaxCompute Java SDK 跑作業,為什麼卡住不動了?”

me: “有 Logview 嗎?發來看下”

A: “沒有,我用的是SDK,沒Logview”

https://www.atatech.org/articles/67812#1 場景二

使用者B

B :“親,用 MaxCompute Java SDK 通路 Table,為什麼卡住半天沒反應?”

me:“卡在哪一行了?”

B:"就 RestClient retry 然後卡住了"

去繁就簡

使用者 A 的問題在于沒有 instance 的 logview,導緻無法追蹤 instance 的運作過程。

通常使用者在建立 instance 後會調用 instance.waitForSuccess() 來等待作業運作完成,一旦作業耗時巨大,程式就卡在這一步了,此時如果有 logview ,就能檢視追蹤檢視作業等待的具體原因了。

使用者 B 的問題在于 sdk 的 Restclient 本身有重試機制,從表面來看就是卡住了,沒有任何輸出。

如果在每次重試的時候都輸出錯誤,就可以快速定位問題節約時間了。我已經遇到好幾個公共雲使用者因為缺包導緻一直卡住幾分鐘才丢出異常,嚴重影響了工作效率。

那麼問題可以歸結為下面兩點:

1【 怎麼使用 MaxCompute Java SDK 生成 instance Logview 】

答案很簡單, MaxCompute Java SDK 提供了 logview 接口,詳情可檢視 

SDK Java Doc
String logview = odps.logview().generateLogView(instance, 7 * 24);           

兩個參數: instance 對象,logview token 逾時時間 (機關:小時)

再次提醒使用者,在使用 SDK 的時候,請為每個 instance 記錄 Logview,一旦遇到問題可快速追蹤。

當然如果改代碼很麻煩,那還有一個絕招。在 MaxCompute Console 中使用 

wait <instance_id>

 指令也可以得到Logview。

2【 能不能在每次重試的時候,都把錯誤輸出呢?】

當然可以。MaxCompute Java SDK 提供了抽象類 

RetryLogger

 詳情可檢視 

public static abstract class RetryLogger {

    /**
     * 當 RestClent 發生重試前的回調函數
     *
     * @param e
     *     錯誤異常
     * @param retryCount
     *     重試計數
     * @param retrySleepTime
     *     下次需要的重試時間
     */
    public abstract void onRetryLog(Throwable e, long retryCount, long retrySleepTime);
  }           

使用者隻需實作一個自己的 

RetryLogger

 子類,然後在初始化 odps 對象的時候使用 

odps.getRestClient().setRetryLogger(new UserRetryLogger());

 就可以将日志輸出。

一個典型的實作如下:

// init odps
odps.getRestClient().setRetryLogger(new UserRetryLogger());

// your retry logger
public class UserRetryLogger extends RetryLogger {

    @Override
    public void onRetryLog(Throwable e, long retryCount, long sleepTime) {
      if (e != null && e instanceof OdpsException) {
        String requestId = ((OdpsException) e).getRequestId();
        if (requestId != null) {
          System.err.println(String.format(
              "Warning: ODPS request failed, requestID:%s, retryCount:%d, will retry in %d seconds.",
              requestId, retryCount, sleepTime));
          return;
        }
      }
      System.err.println(String.format(
          "Warning: ODPS request failed:%s, retryCount:%d, will retry in %d seconds.", e.getMessage(),retryCount,
          sleepTime));
    }
  }           

掌握上面兩種技巧,就可以快速定位問題。