使用MaxCompute Java SDK 执行任务卡住了,怎么办?

场景一

用户A
A: “亲,用 MaxCompute Java SDK 跑作业,为什么卡住不动了?”
me: “有 Logview 吗?发来看下”
A: “没有,我用的是SDK,没Logview”

场景二

用户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

 

<span style="color:#f8f8f2"><code class="language-java">String logview = odps.<span style="color:#e6db74">logview</span>().<span style="color:#e6db74">generateLogView</span>(instance, <span style="color:#ae81ff">7</span> * <span style="color:#ae81ff">24</span>);</code></span>

 

 

两个参数: instance 对象,logview token 超时时间 (单位:小时)

再次提醒用户,在使用 SDK 的时候,请为每个 instance 记录 Logview,一旦遇到问题可快速追踪。

当然如果改代码很麻烦,那还有一个绝招。在 MaxCompute Console 中使用 wait <instance_id> 命令也可以得到Logview。

2【 能不能在每次重试的时候,都把错误输出呢?】

当然可以。MaxCompute Java SDK 提供了抽象类 RetryLogger 详情可查看 SDK Java Doc

 

<span style="color:#333333"><span style="color:#f8f8f2"><code class="language-java"><span style="color:#66d9ef"><span style="color:#f92672">public</span></span> <span style="color:#66d9ef"><span style="color:#f92672">static</span></span> <span style="color:#66d9ef"><span style="color:#f92672">abstract</span></span> <span style="color:#66d9ef"><span style="color:#f92672">class</span></span> RetryLogger {

    <span style="color:slategray"><span style="color:#75715e">/**
     * 当 RestClent 发生重试前的回调函数
     *
     * @param e
     *     错误异常
     * @param retryCount
     *     重试计数
     * @param retrySleepTime
     *     下次需要的重试时间
     */</span></span>
    <span style="color:#66d9ef"><span style="color:#f92672">public</span></span> <span style="color:#66d9ef"><span style="color:#f92672">abstract</span></span> <span style="color:#66d9ef"><span style="color:#f92672">void</span></span> <span style="color:#e6db74"><span style="color:#a6e22e">onRetryLog</span></span>(Throwable e, <span style="color:#66d9ef"><span style="color:#f8f8f2"><span style="color:#f92672">long</span></span></span> retryCount, <span style="color:#66d9ef"><span style="color:#f8f8f2"><span style="color:#f92672">long</span></span></span> retrySleepTime);
  }</code></span></span>

 

用户只需实现一个自己的 RetryLogger 子类,然后在初始化 odps 对象的时候使用 odps.getRestClient().setRetryLogger(new UserRetryLogger()); 就可以将日志输出。

 

一个典型的实现如下:

 

 
<span style="color:#333333"><span style="color:#f8f8f2"><code class="language-java"><span style="color:slategray"><span style="color:#75715e">// init odps</span></span>
odps.<span style="color:#e6db74">getRestClient</span>().<span style="color:#e6db74">setRetryLogger</span>(<span style="color:#66d9ef"><span style="color:#f92672">new</span></span> UserRetryLogger());

<span style="color:slategray"><span style="color:#75715e">// your retry logger</span></span>
<span style="color:#66d9ef"><span style="color:#f92672">public</span></span> <span style="color:#66d9ef"><span style="color:#f92672">class</span></span> UserRetryLogger <span style="color:#66d9ef"><span style="color:#f92672">extends</span></span> RetryLogger {

    <span style="color:#75715e">@Override</span>
    <span style="color:#66d9ef"><span style="color:#f92672">public</span></span> <span style="color:#66d9ef"><span style="color:#f92672">void</span></span> <span style="color:#e6db74"><span style="color:#a6e22e">onRetryLog</span></span>(Throwable e, <span style="color:#66d9ef"><span style="color:#f8f8f2"><span style="color:#f92672">long</span></span></span> retryCount, <span style="color:#66d9ef"><span style="color:#f8f8f2"><span style="color:#f92672">long</span></span></span> sleepTime) {
      <span style="color:#66d9ef"><span style="color:#f92672">if</span></span> (e != <span style="color:#f92672">null</span> && e <span style="color:#66d9ef"><span style="color:#f92672">instanceof</span></span> OdpsException) {
        String requestId = ((OdpsException) e).<span style="color:#e6db74">getRequestId</span>();
        <span style="color:#66d9ef"><span style="color:#f92672">if</span></span> (requestId != <span style="color:#f92672">null</span>) {
          System.err.<span style="color:#e6db74">println</span>(String.<span style="color:#e6db74">format</span>(
              <span style="color:#a6e22e"><span style="color:#e6db74">"Warning: ODPS request failed, requestID:%s, retryCount:%d, will retry in %d seconds."</span></span>,
              requestId, retryCount, sleepTime));
          <span style="color:#66d9ef"><span style="color:#f92672">return</span></span>;
        }
      }
      System.err.<span style="color:#e6db74">println</span>(String.<span style="color:#e6db74">format</span>(
          <span style="color:#a6e22e"><span style="color:#e6db74">"Warning: ODPS request failed:%s, retryCount:%d, will retry in %d seconds."</span></span>, e.<span style="color:#e6db74">getMessage</span>(),retryCount,
          sleepTime));
    }
  }</code></span></span>


掌握上面两种技巧,就可以快速定位问题。

 

 

原文链接
更多技术干货 请关注阿里云云栖社区微信号 :yunqiinsight

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值