SpringBoot RestTemplate线上案例分析和可能造成的问题以及建议

问题来源

线上有一项目,逻辑不是很复杂,主要进行多线程日志上报。某天,程序功能不可用,可进程依在。
按照惯性思维,估计是可能逻辑问题造成的死锁,但是经过code review和运行观察,并没有得到什么可疑现象,困扰许久,当再次出现时,对其现场进行了分析,如下。

现象

程序运行控制台或文件日志停止输出,程序不可用,进程RUNNING状态

点睛之笔

通过观察现场栈,发现大量线程bloked和waiting,你可以使用jstack pid查看。我输出到文件后,在其中找到了我的程序使用的包名,将问题定位到行

在我的程序中,这是一个HTTP POST请求,传输一些数据到公网其他服务器,这里我使用了RestTemplate。

RestTemplate restTemplate = new RestTemplate();
restTemplate.postForObject(host, value, String.class);

通过对其无参构造源码观察,接下来的restTemplate将会使用SimpleClientHttpRequestFactory作为其RequestFactory,SimpleClientHttpRequestFactory连接与读超时均是-1,也就是无超时。

###解决方案
使用RestTemplate有参构造,自定义RequestFactory属性

###说明
我不知道官方为什么会在超时上有这样的使用建议,但是在大多数场景下,这都不太友好。综合服务器带宽与应用消息是否必达基础上,可采用弱请求方式,设置超时,并且使用Guava Retryer是个不错的选择。对了,在出现这个问题的应用里,因为对并发线程使用了CountDownLatch,这也造成了直接锁死,如果是只执行线程,这样的问题要也许等到计算机资源爆表你才会有所察觉。