Spring 异步线程中传递ThreadLocal

  • Post author:
  • Post category:其他


上周熬夜查了一个线上问题,最后复盘会议却没有深入,部门里还是要求快,根据熵增定律,软件系统需要定期注入能力,以维持系统稳定,如果只求快,那么就是牺牲系统的扩展性、健壮性、稳定性。

后期总结一篇生产环境排查问题指南。

今天主体是一个补丁,设计dubbo 超时,spring 异步方法,spring 异步线程传递ThreadLocal 信息。



一、dubbo 超时怎样

{"code":"9","msg":"服务方法(xxx.xxx.xxx:1.0)业务逻辑出错","body":"java.lang.RuntimeException: com.alibaba.dubbo.rpc.RpcException: Failed to invoke the method execute in the service com.fancv.xxx.ccc.client.DamClient. Tried 1 times of the providers [101.51.21.415:30001] (1/1) from the registry zoo1.wwww.cc:30002 on the consumer 12.50.12.148 using the dubbo version 2.5.3. Last error is: Invoke remote method timeout. method: execute, provider: dubbo://10.50.2.145:30001/com.fancv.xxx.ccc.client.DamClient?anyhost=true&application=fancv-wede-sop&check=false&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&group=dubbo&interface=com.fancv.xxx.ccc.client.DamClient&metadata-type=remote&methods=execute&pid=411&pln=fancv-main-sop-gray&protocol=dubbo&release=2.7.7&retries=-1&revision=1.0.0.gray-SNAPSHOT&side=consumer&timeout=5000&timestamp=1640324905371&version=1.0.0-gray, cause: Waiting server-side response timeout by scan timer. start time: 2021-12-27 18:30:28.986, end time: 2021-12-27 18:30:34.018, client elapsed: 0 ms, server elapsed: 5032 ms, timeout: 5000 ms, request: Request [id=180989, version=2.0.0, twoway=true, event=false, broken=false, data=RpcInvocation [methodName=execute, parameterTypes=[class com.fancv.www.sdk.api.RopRequest], 

报错日志显示 dubbo 服务调用超时,测试反馈页面报错,但是程序逻辑执行成功了。



二、 改进方法

spring 异步调用,一般情况下能利用成熟框架的功能就不要自己造轮子,这里采用spring的 @Async 注解

使用方法自行研究

参考 https://www.jianshu.com/p/2d4b89c7a3f1



三、改进中遇到的问题

发现整个文件复制的业务逻辑流程需要用户的登录状态,显而易见,大多数系统会把用户的登录状态放入在Context 中,使用ThreadLocal 的方式进行传递,那么起了一个异步线程之后,登录信息如果不做任何处理就消失了,程序报错。



1.方法传递,把用户信息当做一个参数 传递的新的线程

简单,容易理解



2.很多场景需要异步调用,那么可以使用一个自定义的注解

拦截件处理加了注解的方法,增加ThreadLocal的传递过程。

或许不就的将来spring 框架会支持。