2.异步回调(Lambda表达式)代码块中的异常处理有两种策略:1)一定要通过exceptionally方法或者whenComplete对异常进行捕获处理,否则会导致Lambda表达式异常退出,后续操作被忽略,最终导致业务逻辑跑飞。

2)运行期异常,通常是无法抛出来由调用方处理的,需要在发生异常的地方就地捕获和处理。

3。

1。

2超时控制

异步代码块(Lambda表达式)中可能会涉及到多种业务逻辑操作,例如:

1.数据库、缓存、MQ等中间件平台调用。

2.第三方接口调用。

3.级联嵌套其它微服务调用。

对于异步的超时控制,建议策略如下:

1.对单个原子的中间件、第三方接口、微服务做超时控制。

2.不建议直接对异步代码块(Lambda表达式)整体做超时控制,例如包装出一个支持异步超时的CompletableFuture,主要原因如下:

超时并不能确保中断当前正在执行的业务逻辑,例如同步Redis缓存调用。

如果超时发生时,正好又发起了一次异步RPC调用,创建了一个新的CompletableFuture,外层超时之后,已经创建的CompletableFuture异步回调仍然可能会被执行,这会带来各种混乱。

由于异步代码块(Lambda表达式)中的业务逻辑可能会非常复杂,所以超时之后的补偿操作非常困难。

例如充值操作已经成功了,但是外层调用方超时失败了,这会给后续业务的处理带来很多困难,因为超时发生时调用方并不知道异步代码块中的哪些操作被执行,哪些没被执行。

没有超时控制之后,要确保CompletableFuture能够正常或者异常的结束,否则会导致CompletableFuture积压,最终发生OOM。

3。

1。

3上下文传递

在传统的同步RPC调用时,业务往往通过线程变量来传递上下文,例如:TraceID、会话Session、IP等信息。

异步化之后,由于潜在的线程切换和线程被多个消息交叉复用,通常不建议继续使用线程变量传递上下文。

异步化之后,上下文传递的建议策略:

1.如果是Lambda表达式,可以直接引用局部变量,通过变量引用的方式将上下文信息传递到Lambda表达式中,后续可以通过方法传参等层层传递下去。

2.在所有发生线程切换的地方,显式的进行上下文信息的拷贝和清理,特别需要注意的是隐式线程切换,例如Hystrix,底层会自己启线程池。

3.建议通过调用级的消息上下文来做参数传递,每个上下文都关联一次RPC调用,调用完成之后自动清理掉。

4.异步化之后,需要排重点查所有使用ThreadLocal的地方,通常情况下都会存在问题,需要做改造。

3。

1。

4异步回调地狱问题

如果使用的是JDK8的CompletableFuture,它支持对异步操作结果做编排以及级联操作,能够比较好的解决类似JS和传统Future-Listener的回调地域问题,感兴趣的读者可以体会下CompletableFuture的异步化接口。

如果想免费学习Java工程化、高性能及分布式、深入浅出。

微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java架构交流群:479499375,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。


Author