背景
各个子系统之间通过feign调用,每个服务提供方需要验证每个请求header里的token。
public void invokeFeign() throws Exception {
feignService1.method();
feignService2.method();
feignService3.method();
....
}
定义拦截每次发送feign调用拦截器RequestInterceptor的子类,每次发送feign请求前将token带入请求头
@Configuration
public class FeignTokenInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
public void apply(RequestTemplate template) {
//上下文环境保持器,拿到刚进来这个请求包含的数据,而不会因为远程数据请求头被清除
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();//老的请求
if (request != null) {
//同步老的请求头中的数据,这里是获取cookie
String cookie = request.getHeader("token");
template.header("token", cookie);
}
}
.....
}
这样便能实现系统间通过同步方式feign调用的认证问题。但是如果需要在invokeFeign方法中feignService3的方法调用比较耗时,并且invokeFeign业务并不关心feignService3.method()方法的执行结果,此时该怎么办。
方案1:
修改feignService3.method()方法,将其内部实现修改为异步,这种方案依赖服务的提供方,如果feignService3服务是其他业务部门维护,并且无法修改实现为异步,此时只能采取方案2.
方案2:
通过线程池调用feignServie3.method()
public void invokeFeign() throws Exception {
feignService1.method();
feignService2.method();
executor.submit(()->{
feignService3.method();
});
....
}
怀着期待的心情开启了尝试,你会发现调用feignService3方法并没有成功,查看日志你将会发现是由于feign发送request请求的header中未携带token导致。于是百度了下feign异步调用传参,网上大部分的解决方案,如下
public void invokeFeign() throws Exception {
feignService1.method();
feignService2.method