Feign异步调用丢失请求头问题

当使用线程池执行异步任务调用其他服务时,由于请求头信息存储在ThreadLocal中,新线程无法获取导致丢失。解决方案是在每个异步任务开始前,将当前线程的请求头信息复制并设置到新线程中,确保请求头信息的传递。
摘要由CSDN通过智能技术生成

起因:客户端带请求头请求接口–>接口开启新线程调用其他服务的接口会导致请求头丢失问题;

/**
 * 伪代码
 */
public void test(){
    
    // 自定义线程池,一般一个服务定义1~2个线程池,所有多线程执行都公用同个线程池  
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
        10,	//核心线程数
        200,//最大线程数
        10, TimeUnit.SECONDS,	// 非核心线程空闲时存活时间,时间单位
        new LinkedBlockingDeque<>(10000),	// 阻塞队列
        Executors.defaultThreadFactory(),	// 线程创建工厂,一般用默认
        new ThreadPoolExecutor.AbortPolicy()); // 拒绝策略,如果队列满了,按照我们指定的拒绝策略执行任务
    
    //异步任务1
    CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {

        //调用其他服务的业务代码(会有请求头丢失问题)
    }, threadPoolExecutor);
    
    //异步任务2
    CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {

        //调用其他服务的业务代码(会有请求头丢失问题)
    }, threadPoolExecutor);
    
    // future1和future2都执行完成之后继续再执行下面的业务代码
    CompletableFuture.allOf(future1,future2).get();
    
    // 业务代码
} 

原因:Feign 服务间调用请求头丢失问题,我们是加了一个拦截器去将请求头的信息重新设置到Request对象中再去请求其他服务的接口,获取ServletRequestAttributes我们是通过RequestContextHolder.getRequestAttributes()这个方法,从RequestContextHolder对象中拿数据是通过ThreadLocal,只有同个线程才能从ThreadLocal中拿到数据,我们开启了新线程去调用其他接口,那当然是拿不到数据;

解决方案

从当前线程拿到请求头信息,调用其他服务时将请求头设置进去;

// 获取当前线程请求头信息
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

//异步任务1
CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
	//远程调用之前设置请求头
    RequestContextHolder.setRequestAttributes(requestAttributes);

    //调用其他服务的业务代码(会有请求头丢失问题)
}, threadPoolExecutor);

//异步任务2
CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
    //远程调用之前设置请求头
    RequestContextHolder.setRequestAttributes(requestAttributes);

    //调用其他服务的业务代码(会有请求头丢失问题)
}, threadPoolExecutor);

// future1和future2都执行完成之后继续再执行下面的业务代码
CompletableFuture.allOf(future1,future2).get();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值