由RestTemplate引发的加班惨案

前言

今天真是美好的一天呢,股市一如往常地绿,我一如往常地坐在办公桌前敲代码。

上级交给我一个刷新历史数据的需求,一般刷新历史数据可以采用的方式有SQL脚本以及定时任务。

以往大多数时候我都是采用SQL脚本的方式,因为这次涉及接口的调用,于是打算使用后台任务来实现。

本来很日常的一个任务,没想到还会有意外的插曲。


过程

需求

根据新的业务逻辑修复历史数据,就是更新某些表的某些字段。

这里的业务就不详细介绍了。反正与技术无关。


设计和实现

1、将 需要更新的主表的主键 通过脚本刷到临时表,初始化为待处理状态。
(这样做是为了修复历史数据时不影响到其他业务对主表的操作)

2、创建临时定时任务,用代码实现取数的逻辑,其中涉及两次内部接口的调用

3、批量处理完数据后,更新主表数据以及临时表的状态。

4、将接口的调用记录到临时日志表,主要字段有主表主键、接口标志、发起请求时间、返回结果时间、返回数据


测试结果

上面的步骤一气呵成,自以为胸有成竹。当然开发机也有自测过了,流程是没问题的。

于是提交给测试部进行测试,此时已经接近下班时间了。

结果测试告知数据跑着跑着就卡住了,待处理的数据量没有继续减少了。

想想心都凉了,这是要加班的节奏呀,于是连忙开始分析。

查看了临时表,待处理的数据量确实没有继续减少了;

再查看临时日志表,按时间降序后,发现大多数接口的调用间隔时间都是毫秒级别的,但是极少数调用的间隔时间很长,大到几分钟。现在就是卡死不动了,也没新的日志产生。

那时候怀疑是逻辑问题,于是检查了一遍,确实找不出问题,因为本身这个任务的处理逻辑也不复杂。

于是我重启了测试机的定时任务,发现又好使了。。。


分析

从日志看确实没打印有效的信息,这可能是我日志埋点埋得不好。我的锅。

根据这现象,在网上查找了一些资料以及和同事讨论后,锁定了一个方向,那就是跟请求接口有关的RestTemplate

在网络上其中有一篇文章《记录RestTemplate一个自己挖的坑》如下分析:
来自网络
另外我单独测了任务中所调用的接口,响应时间平均下来也是毫秒级别。

所以越来越确定是由于Http请求造成这次任务的异常。

查看了这次任务中使用的请求工具,也就是RestTemplate

以前倒没怎么注意这个小家伙,这次找了一些关于它的资料。


解决

解决方法就是为RestTemplate设置超时时间,避免过长的无响应连接所带来的耗时影响。

连接失败则断开,再进行重连即可。

原先使用的默认RestTemplate
  <bean id="restTemplate" class="org.springframework.web.client.RestTemplate" />

设置了超时的RestTemplate
  <!-- 同步restful,3s超时 -->
  <bean id="restTemplate3sTimeout" class="org.springframework.web.client.RestTemplate">
    <constructor-arg>
      <bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
        <property name="readTimeout" value="3000"/>
        <property name="connectTimeout" value="3000"/>
      </bean>
    </constructor-arg>
  </bean>
发布了107 篇原创文章 · 获赞 88 · 访问量 26万+

猜你喜欢

转载自blog.csdn.net/Code_shadow/article/details/104978891