• feign远程调用丢失请求头


    1、feign 远程调用丢失请求头的问题

    原因:feign不会同步request的请求头。

    解决方案:使用interceptor将用户请求的请求头设置给feign代理的请求

    /**
     * @DESCRIPTION feign的请求拦截器,用于将用户请求头设置给feign代理后的请求,防止代理后丢失请求头
     * @Author yaya
     * @DATE 2022/10/7
     */
    @Configuration
    public class FeignInterceptor {
    
    
        @Bean("requestInterceptor")
        public RequestInterceptor requestInterceptor(){
            return new RequestInterceptor() {
                @Override
                public void apply(RequestTemplate requestTemplate) {
                    // 通过RequestContextHolder拿到用户的request
                    ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                    HttpServletRequest request = requestAttributes.getRequest();
                    String cookie = request.getHeader("Cookie");
                    // 将用户的cookie设置给feign代理后的请求
                    requestTemplate.header("Cookie", cookie);
                }
            };
        }
    }
    

    源代码跟踪:

    1、feign远程调用首先会进ReflectiveFeign.invoke方法

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if (!"equals".equals(method.getName())) {
                    if ("hashCode".equals(method.getName())) {
                        return this.hashCode();
                    } else {
    					// 如果不是hashCode、toString方法则会调用目标方法
                        return "toString".equals(method.getName()) ? this.toString() : ((MethodHandler)this.dispatch.get(method)).invoke(args);
                    }
                } else {
                    try {
                        Object otherHandler = args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
                        return this.equals(otherHandler);
                    } catch (IllegalArgumentException var5) {
                        return false;
                    }
                }
            }
    

    2、然后会进到SynchronousMethodHandler.invoke方法

    public Object invoke(Object[] argv) throws Throwable {
            RequestTemplate template = this.buildTemplateFromArgs.create(argv);
            Options options = this.findOptions(argv);
            Retryer retryer = this.retryer.clone();
    
            while(true) {
                try {
                    return this.executeAndDecode(template, options);
                } catch (RetryableException var9) {
                    RetryableException e = var9;
    
                    try {
                        retryer.continueOrPropagate(e);
                    } catch (RetryableException var8) {
                        Throwable cause = var8.getCause();
                        if (this.propagationPolicy == ExceptionPropagationPolicy.UNWRAP && cause != null) {
                            throw cause;
                        }
    
                        throw var8;
                    }
    
                    if (this.logLevel != Level.NONE) {
                        this.logger.logRetry(this.metadata.configKey(), this.logLevel);
                    }
                }
            }
        }
    
        Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {
            Request request = this.targetRequest(template);
            if (this.logLevel != Level.NONE) {
                this.logger.logRequest(this.metadata.configKey(), this.logLevel, request);
            }
    
            long start = System.nanoTime();
    
            Response response;
            try {
                response = this.client.execute(request, options);
                response = response.toBuilder().request(request).requestTemplate(template).build();
            } catch (IOException var13) {
                if (this.logLevel != Level.NONE) {
                    this.logger.logIOException(this.metadata.configKey(), this.logLevel, var13, this.elapsedTime(start));
                }
    
                throw FeignException.errorExecuting(request, var13);
            }
    
            long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
            if (this.decoder != null) {
                return this.decoder.decode(response, this.metadata.returnType());
            } else {
                CompletableFuture<Object> resultFuture = new CompletableFuture();
                this.asyncResponseHandler.handleResponse(resultFuture, this.metadata.configKey(), response, this.metadata.returnType(), elapsedTime);
    
                try {
                    if (!resultFuture.isDone()) {
                        throw new IllegalStateException("Response handling not done");
                    } else {
                        return resultFuture.join();
                    }
                } catch (CompletionException var12) {
                    Throwable cause = var12.getCause();
                    if (cause != null) {
                        throw cause;
                    } else {
                        throw var12;
                    }
                }
            }
        }
    

    在executeAndDecode方法中会执行一行代码Request request = this.targetRequest(template);这个方法就是处理request的逻辑。

    3、targetRequest处理request

        Request targetRequest(RequestTemplate template) {
    		// 遍历执行interceptor
            Iterator var2 = this.requestInterceptors.iterator();
    
            while(var2.hasNext()) {
                RequestInterceptor interceptor = (RequestInterceptor)var2.next();
                interceptor.apply(template);
            }
    
            return this.target.apply(template);
        }
    

    在targetRequest方法中会遍历执行interceptor。
    private final List requestInterceptors;
    我们往容器中放的interceptor就会被执行,request中就会有请求头了。

    2、feign异步情况丢失上下文

    原因:异步请求,request不是同一个,threadLocal中获取不到。

    解决方案:在异步编排时手动在新线程中共享下数据:RequestContextHolder.setAttribute()。

  • 相关阅读:
    Linux系统命令与权限
    有关Linux目录相关内容
    Linux的命令以及基本使用
    操作系统的基本知识与Linux系统简介
    IT知识架构与操作系统简介
    windows下nginx支持php的配置
    提权操作函数
    c++内存中字节对齐问题详解 [ 转载 ]
    STL 容器效率的对比
    C++ 四种类型转换的介绍
  • 原文地址:https://www.cnblogs.com/yanghuanxi/p/16817992.html
Copyright © 2020-2023  润新知