坑:异步调用其他服务避免使用AsyncRestTemplate
现象
订单服务的几个流程推动接口,出现了大量异常。持续20分钟。
排查
初步查看日志,发现这段时间有大量异常抛出,全部都是
java.lang.IllegalStateException: No instances available for travel-push。如图:
比较奇怪的是push全都是异步调用的。按理说不能影响到主流程才对。
查代码发现,用的异步调用,是用的org.springframework.web.client.AsyncRestTemplate
AsyncRestTemplate这个还是标注成废弃的
AsyncRestTemplate处理异步层面比较靠近调用,所以当被调用服务不可达的时候,这里会抛出异常,还是挺危险的。
并且这种方式不能传递traceId。
结论
可以自己写异步替代AsyncRestTemplate,利用CompletableFuture显式处理成功和失败。
同时可以指定executor来传递traceId。详见 异步线程带上traceId
我们在做异步处理的时候。用logger打日志以及http跨模块调用时,traceId都会因为线程改变而丢失原来的跟踪信息。在排查问题看日志时很不方便。
traceId其实是腾讯tsf基于spring cloud sleuth搞的,是trace和span中trace的id。
在其官方文档中,提供了几种异步传递trace/span的机制。
原地址:https://cloud.spring.io/spring-cloud-sleuth/reference/html/#asynchronous-communication
举个例子,
我们比较常用的是通过executor去创建一个异步线程,可以用LazyTraceExecutor去包装这个executor即可。
首先根据需要的场景,指定线程数等参数配置一个executor的bean。
|
在需要的地方注入,然后按原来的方式使用即可。
|