坑:异步调用其他服务避免使用AsyncRestTemplate

导读:本篇文章讲解 坑:异步调用其他服务避免使用AsyncRestTemplate,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

现象

坑:异步调用其他服务避免使用AsyncRestTemplate

订单服务的几个流程推动接口,出现了大量异常。持续20分钟。

排查

初步查看日志,发现这段时间有大量异常抛出,全部都是

java.lang.IllegalStateException: No instances available for travel-push。如图:

坑:异步调用其他服务避免使用AsyncRestTemplate

比较奇怪的是push全都是异步调用的。按理说不能影响到主流程才对。

查代码发现,用的异步调用,是用的org.springframework.web.client.AsyncRestTemplate

坑:异步调用其他服务避免使用AsyncRestTemplate

AsyncRestTemplate这个还是标注成废弃的

坑:异步调用其他服务避免使用AsyncRestTemplate

AsyncRestTemplate处理异步层面比较靠近调用,所以当被调用服务不可达的时候,这里会抛出异常,还是挺危险的。

并且这种方式不能传递traceId。

结论

可以自己写异步替代AsyncRestTemplate,利用CompletableFuture显式处理成功和失败。

同时可以指定executor来传递traceId。详见 异步线程带上traceId

坑:异步调用其他服务避免使用AsyncRestTemplate

附:异步线程带上traceId

我们在做异步处理的时候。用logger打日志以及http跨模块调用时,traceId都会因为线程改变而丢失原来的跟踪信息。在排查问题看日志时很不方便。

traceId其实是腾讯tsf基于spring cloud sleuth搞的,是trace和span中trace的id。

在其官方文档中,提供了几种异步传递trace/span的机制。

坑:异步调用其他服务避免使用AsyncRestTemplate

原地址:Spring Cloud Sleuth

举个例子,

我们比较常用的是通过executor去创建一个异步线程,可以用LazyTraceExecutor去包装这个executor即可。

首先根据需要的场景,指定线程数等参数配置一个executor的bean。

@Bean(name = "myExecutorService")

public Executor getMyExecutorService() {

    BasicThreadFactory threadFactory = new BasicThreadFactory.Builder()

            .namingPattern("shunfeng-pool-%d")

            .daemon(true)

            .build();



    ThreadPoolExecutor threadPoolExecutor =

            new ThreadPoolExecutor(threadPoolConfig.getCorePoolSize(),

                    threadPoolConfig.getMaxPoolSize(),

                    threadPoolConfig.getKeepAliveSeconds(),

                    TimeUnit.SECONDS,

                    new LinkedBlockingQueue<>(1024),

                    threadFactory,

                    new ThreadPoolExecutor.AbortPolicy());



    return new LazyTraceExecutor(beanFactory, threadPoolExecutor);

}

在需要的地方注入,然后按原来的方式使用即可。

@Autowired

@Qualifier("myExecutorService")

Executor executor;





private void asyncDoSomething1() {

    log.info("async.");

    CompletableFuture.runAsync(() -> doSomething(), executor);

}



private void asyncDoSomething2() {

    log.info("async.");

    executor.execute(() -> doSomething());

}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/71382.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!