一、Feign远程调用丢失请求头问题
Feign在远程调用时,会重新包装请求(请求路径,请求参数)但是不会携带请求头,所以在到达被调服务时没有请求头信息
1、 SynchronousMethodHandler
@Override
public Object invoke(Object[] argv) throws Throwable {
RequestTemplate template = buildTemplateFromArgs.create(argv);
Options options = findOptions(argv);
Retryer retryer = this.retryer.clone();
while (true) {
try {
return executeAndDecode(template, options);
} catch (RetryableException e) {
try {
retryer.continueOrPropagate(e);
} catch (RetryableException th) {
Throwable cause = th.getCause();
if (propagationPolicy == UNWRAP && cause != null) {
throw cause;
} else {
throw th;
}
}
if (logLevel != Logger.Level.NONE) {
logger.logRetry(metadata.configKey(), logLevel);
}
continue;
}
}
}
2、解决方案
在Feign重新包装请求时,使用 RequestInterceptor 拦截器,把老请求中请求头重新保存到新的请求中二、多线程下Feign远程调用丢失上下文
- 解决方案
把线程-1中的上下文内容拷贝到 线程-2 、 线程-3
public OrderConfirmVo orderConfirm() {
OrderConfirmVo orderConfirm = new OrderConfirmVo();
//获取登录用户
MemberEntity memberInfo = LoginInterceptor.threadLocal.get();
log.info("主线程。。。" + Thread.currentThread().getId());
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
//1、获取用户地址
CompletableFuture<Void> addressFuture = CompletableFuture.runAsync(() -> {
log.info("addressFuture线程。。。" + Thread.currentThread().getId());
// 把主线程中的属性共享给其他线程
RequestContextHolder.setRequestAttributes(requestAttributes);
R addressRes = this.memberClient.fetchAddressByMemberId(memberInfo.getId());
String addressJSON = JSON.toJSONString(addressRes.get("data"));
List<MemberReceiveAddressEntity> memberReceiveAddressEntityList = JSON.parseObject(addressJSON, new TypeReference<List<MemberReceiveAddressEntity>>() {
});
if (memberReceiveAddressEntityList != null && memberReceiveAddressEntityList.size() > 0) {
List<MemberAddressTo> addressList = memberReceiveAddressEntityList.stream().map(address -> {
MemberAddressTo memberAddressTo = new MemberAddressTo();
BeanUtils.copyProperties(address, memberAddressTo);
return memberAddressTo;
}).collect(Collectors.toList());
orderConfirm.setAddressList(addressList);
}
}, this.executor);
//2、购物项
CompletableFuture<Void> cartItemFuture = CompletableFuture.runAsync(() -> {
log.info("addressFuture线程。。。" + Thread.currentThread().getId());
// 把主线程中的属性共享给其他线程
RequestContextHolder.setRequestAttributes(requestAttributes);
R cartRes = this.cartClient.fetchSelectedCartItems();
String cartJson = JSON.toJSONString(cartRes.get("data"));
List<CartItem> cartItemToList = JSON.parseObject(cartJson, new TypeReference<List<CartItem>>() {
});
if (cartItemToList != null && cartItemToList.size() > 0) {
List<CartItemTo> cartItemList = cartItemToList.stream().filter(item -> item.getCheck() == true).map(item -> {
CartItemTo itemTo = new CartItemTo();
BeanUtils.copyProperties(item, itemTo);
return itemTo;
}).collect(Collectors.toList());
orderConfirm.setCartItemList(cartItemList);
}
}, this.executor);
//3、优惠券
orderConfirm.setIntegration(memberInfo.getIntegration());
try {
CompletableFuture.allOf(addressFuture, cartItemFuture).get();
} catch (Exception e) {
e.printStackTrace();
throw new RavenException(RavenCodeEnum.THREAD_POOL_FAIL);
}
return orderConfirm;
}