Feign远程调用中的各种问题

发布于 2023-01-04  104 次阅读


一、丢失请求头问题

1、问题原因

feign在远程调用时,会创建一个新请求,而这个新请求中没有任何请求头。

feigen远程调用丢失请求头问题.png

2、解决方法

自定义拦截器,将远程调用的请求头必须和老请求同步

/**
 * @author : ctc
 * @createTime : 2023/1/4 21:12
 */
@Configuration
public class guliFeignConfig {

    @Bean("requestInterceptor")
    public RequestInterceptor requestInterceptor() {
        return new RequestInterceptor(){
            @Override
            public void apply(RequestTemplate template) {
                // 1、使用RequestContextHolder拿到初始请求
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                HttpServletRequest request = attributes.getRequest();
                // 同步请求头数据
                String cookie = request.getHeader("Cookie");
                // 同步了cookie
                template.header("Cookie",cookie);
            }
        };
    }
}

二、丢失上下文问题

1、原因

fegin在异步调用中会出现丢失上下文问题,老线程和新线程中的ThreadLocal无法共享,在新线程中无法获取老请求

fegin远程调用丢失上下文问题.png

二、解决方法

在将数据从主线程复制一份到新线程

在主线程中保存一份数据:

// 获取之前的请求
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

设置到新线程:

// 共享请求
RequestContextHolder.setRequestAttributes(requestAttributes);

例:

CompletableFuture<Void> addressFuture = CompletableFuture.runAsync(() -> {
    // 共享请求
    RequestContextHolder.setRequestAttributes(requestAttributes);

    R r = memberFeignService.getAddress(member.getId());
    List<MemberAddressVo> address = r.getData(new TypeReference<List<MemberAddressVo>>() {
    });
    confirmVo.setMemberAddressVos(address);
}, executor);