feign远程调用丢失请求头(header)解决方案以及原理分析!
程序员文章站
2022-03-22 21:20:53
...
一、Feign远程调用丢失请求头问题
Feign在远程调用时,会重新包装请求(请求路径,请求参数)但是不会携带请求头,所以在到达被调服务时没有请求头信息
原因:
@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;
}
}
}
feign会重新封装请求模板。这个模板中没有请求头信息。
解决方案,利用feign拦截器,手动添加请求头:
参考代码:
@Configuration
public class GuliFeignConfig {
/**
* 解决fein远程调用丢失请求头
* @return
*/
@Bean("requestInterceptor")
public RequestInterceptor requestInterceptor() {
return new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
// 1、RequestContextHolder 拿到当前的请求
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null) {
// 原始请求 页面发起的老请求
HttpServletRequest request = attributes.getRequest();
if (request != null) {
// 获取原始请求的头数据 cookie
String cookie = request.getHeader("Cookie");
// 给feign生成的心请求设置请求头cookie
template.header("Cookie", cookie);
}
}
}
};
}
}
2、Feign异步调用丢失请求头问题
解决:获取之前的请求,让每个异步任务的线程共享ThreadLocal数据
/**
* 解决异步任务拿不到ThreadLocal里的数据
* 获取之前的请求,让每个异步任务的线程共享ThreadLocal数据
*/
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
CompletableFuture<Void> getAddressTask = CompletableFuture.runAsync(() -> {
// 解决异步任务拿不到ThreadLocal里的数据
RequestContextHolder.setRequestAttributes(requestAttributes);
//...
}, executor);