跳到主要内容

多线程调用服务情况下解决数据丢失

在上一章节讲解了在服务调用的过程中,由于flux是异步调用,所以线程发生了变化,解决ThreadLocal在此情况下的数据传递问题。 但还并没有完,关于多线程还有其他的问题,用案例来模拟下

案例

@RequestMapping(value = "/call/async")
public Map<String,Map<String,String>> callAsync(){
Map<String,Map<String,String>> resultMap = new HashMap<>(2);
Map<String, String> consumerServiceMap = metaDataOperation.getInfo();
resultMap.put("consumer-service",consumerServiceMap);
threadPoolExecutor.execute(() -> {
System.out.println("线程池调用线程:"+Thread.currentThread().getName());
Map<String, String> providerServiceMap = providerClient.call();
resultMap.put("provider-service",providerServiceMap);
});
return resultMap;
}

在线程池中调用了 provider-service,执行过程会发现,从请求头中获取数据时,从 BaseParameterHolder 中获取 ServletRequestAttributes 为空,我把这部分代码贴出来

public String getValueFromHeader(String name) {
//先获取到HttpServletRequest,然后再获取到请求头的值
HttpServletRequest request = getHttpServletRequest();
if (request != null) {
return request.getHeader(name);
}
return null;
}

public HttpServletRequest getHttpServletRequest() {
//先从线程上下文中获取HttpServletRequest,如果没有再从ServletRequestAttributes中获取
ServletRequestAttributes attributes = null;
Object parameter = BaseParameterHolder.getParameter(WorkConstant.REQUEST_ATTRIBUTES);
if (Objects.nonNull(parameter)) {
attributes = (ServletRequestAttributes) parameter;
}
if (attributes == null) {
attributes = getRequestAttributes();
}
if (attributes == null) {
return null;
}
return attributes.getRequest();
}

public ServletRequestAttributes getRequestAttributes() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes == null) {
return null;
}
return (ServletRequestAttributes) requestAttributes;
}

有人看了可能会有个疑问,代码中先从 BaseParameterHolder 中获取,下面不还是有个从 RequestContextHolder 再获取吗,不好意思 RequestContextHolder 是Spring提供的,它也是 ThreadLocal 结构。这个只是为了代码健壮性,取其他数据的作用。

那这要怎么处理?先把上一章节提到的线程切换过程再看一下