restTemplate超时时间引发的生产事故

Posted housh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了restTemplate超时时间引发的生产事故相关的知识,希望对你有一定的参考价值。

1、现象:

  今天下午公司客户群里突然报警,说订单没有推送服务商,经排查发现是rabbitmq堵住了,查询elk和监控没有发现业务异常或超时日志。

  通过rabbitmq后面发现一个队列有异常,队列不ack,未消费数量一直增长,怀疑服务假死,只能保留现场,重启服务,下面是服务重启前后队列截图

 

 

技术图片

技术图片

 

 

2、分析

  为什么服务重启后队列立马消费一空,证明三方服务商的接口没有问题,经过代码查找发现调用三方用的是restTemplate,核心代码如下:

 

 1 @Service
 2 public class OrderStatusChangePushService {
 3     private static Logger logger = LoggerFactory.getLogger(OrderStatusChangePushService.class);
 4     @Autowired
 5     private RestTemplate restTemplate;
 6     
 7     public ResponseEntity<PlatformBaseResponse> notify2Thirdparty(OrderInfoReqs orderInfo, String callbackUrl, AssortmentOpenApiEncryptDto encryptConfig, String operateType) {
 8         PlatformBaseRequest request = getRequest(orderInfo, encryptConfig, operateType);
 9         HttpHeaders headers = new HttpHeaders();
10         headers.setContentType(MediaType.APPLICATION_JSON);
11         HttpEntity<PlatformBaseRequest> platformBaseRequestHttpEntity = new HttpEntity<>(request, headers);
12         ResponseEntity<PlatformBaseResponse> exchange = null;
13         exchange = restTemplate.exchange(callbackUrl, HttpMethod.POST, platformBaseRequestHttpEntity, PlatformBaseResponse.class);
14         return exchange;
15     }
16 }

 

 1 @SpringBootApplication
 2 public class PlatformOrderConsumerApplication extends SpringBootServletInitializer {
 3     @Bean
 4     RestTemplate restTemplate() {
 5         return new RestTemplate();
 6     }
 7 
 8     public static void main(String[] args) {
 9         SpringApplication.run(PlatformOrderConsumerApplication.class, args);
10     }
11 }

 

 

发现restTemplate用的是直接new的,未重写连接池也未设置超时时间。看源码得知底层用的jdk的httpurlconnection,若readTimeOut和connectionTimeOut没有设置,那请求是没有超时时间的,导致请求一直hang住。

技术图片

 

 

 技术图片

 

 

 3、结论

  restTemplate没有设置超时时间,导致单挑消息不能ack,hang住了整个队列(因为业务需求,一个队列只能单线程消费)

    restTemplate如果没有重写连接池,默认用的SimpleClientHttpRequestFactory,SimpleClientHttpRequestFactory默认的readTimeOut=-1,connectionTimeOut=-1, 导致jdk的HttpUrlConnection是不会超时,进而hang死整个队列

 

以上是关于restTemplate超时时间引发的生产事故的主要内容,如果未能解决你的问题,请参考以下文章

记一次分布式锁使用不当引发生产事故.....

Mysql数据库未添加索引引发的生产事故

记录一次生产事故引发的登录流程梳理

记一次最近生产环境项目中发生的两个事故及处理方法

Azure - SqlBulkCopy 引发超时过期异常

如何在 RestTemplate 中添加超时