ThreadLocal没有及时释放,造成数据不一致
程序员文章站
2022-06-09 15:03:37
...
问题描述:
请求一个接口,有时候返回的是上一次的结果,有时候又返回正确,有时候能请求到接口有时候没请求到也返回数据,返回结果不是想要的,造成数据 不一致。
很神奇!!!
public class ReqContextHolder {
private static final ThreadLocal<ReqContext> contextMap = new ThreadLocal<>();
private static final Map<String,Object> sqlSessionMap = new HashMap<>();
public static ReqContext getReqContext() {
ReqContext reqContext = contextMap.get();
if(reqContext == null){
throw new RuntimeException("没有创建ReqContext");
}
return reqContext;
}
public static void removeReqContext() {
if(contextMap.get() != null) {
contextMap.remove();
}
}
public static void setReqContext(ReqContext reqContext) {
contextMap.set(reqContext);
}
}
问题排查:
1、一开始怀疑是负载均衡的问题,请求到了别的地方,毕竟场景非常像,但是看了配置信息排除了这种情况
2、再者怀疑是Cookie的问题,单点登录故障、可别的地方都可以至于我的接口不行
3、最后去dump了多线程日志,发现是ThreadLocal的数据没及时释放造成的,ThreadLocal存储的上下文没有及时清除,导致问题描述里边出现的情况:有时候断点没进接口却返回了数据,而且是前几次请求的数据
解决办法:
在使用完后即使清除ThreadLocal数据,在finally清除:
public static void removeReqContext() {
if(contextMap.get() != null) {
contextMap.remove();
}
}
例如:
/**
* 从json字符串中装载对象到reqContext
* @param entityClass
* @param jsonValue
* @param <T>
*/
private <T extends AbstractEntity> void setEntityFromJson(Class<T> entityClass, String jsonValue) {
ReqContext reqContext = reqContextFactory.createReqContext();
try {
T entityItem = JSONObject.parseObject(jsonValue, entityClass);
if(entityItem != null){
reqContext.cacheRefEntity(entityItem);
}
} catch (Exception e) {
logger.error(e);
throw new RuntimeException(e);
} finally {
ReqContextHolder.removeReqContext();
}
}
下一篇: 问题排查记录