我是靠谱客的博主 花痴香烟,最近开发中收集的这篇文章主要介绍OpenFeign异步线程调用丢失请求头问题排查记录前言分析寻找解决途径,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言

事情的起因是因为我们在业务的日志中发现偶尔会出现一个这样的报错,而且正是因为这样的一个报错,导致我们一些用户的权益下发失败。
丢失请求头

分析

看这个报错提示,能看出来是content-type请求时没带上。我们项目中使用的是openFeign进行微服务调用,那为什么会没有content-type呢?
查看代码观察到,对于的报错代码都使用了线程池进行异步业务处理,主线程则立即返回,线程池中线程调用时产生了如下的报错。

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>

寻找解决途径

知道表象后我开始查阅百度谷歌资料…

直接github提个issue

issue地址
当时提了一个issue,那时候报错表象可能不一样,但究其原因是丢失了请求头content-type。但大佬们回答的效率确实不高,还建议我使用缺省的content-type。

本地搭建服务测试

发现服务能够正常的调用,但是当将feign异步时,主线程提前完成则失败,主线程等待则成功。

@RestController
public class TestController {

    @Autowired
    private AsyncFeignClient asyncFeignClient;
    
    @PostMapping("/async")
    public String async() throws InterruptedException {
        Thread thread = new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
           asyncFeignClient.postReq(new Model(),"123");
        });
        thread.start();
        thread.join();

        return "success";
    }
}

@FeignClient(url = "127.0.0.1:9001",name = "async-feign",contextId = "identity")
public interface AsyncFeignClient {

    @PostMapping(value = "/transport")
    String postReq(@RequestBody Model mobile, @RequestHeader("token") String token);
}

去掉 thread.join() 服务端则会出现如下报错
在这里插入图片描述

源码debug

于是,借着这次机会再捋一下老熟人feignclient请求的流程。具体的流程太长,另起一篇记录。
如下是关键点

一开始进入feign调用后其实调用的是代理类的invoke方法,并且由于声明了请求头和@RequestBody所以template生成时有如下的头部
在这里插入图片描述
再往下走 executeAndDecode方法
在这里插入图片描述
在这里targetRequest之后头就被清空了,进去里面看到其实是自定义了拦截器导致
在这里插入图片描述

所以年轻人,自定义拦截器一定要小心。

也正是因为拦截器中的下面代码对template头部进行了清空 而究其原因就是在主线程结束后异步线程并没有上下问但他却取到了下面的request。
在这里插入图片描述
在这里插入图片描述
说来也奇怪为什么这里传空就不是追加而是清除还不是很理解。

到这里排查就结束了 ?

另外原因

其实这个问题还有一个原因,我的同事在误以为为什么无法传递头部的时候使用了如下代码

RequestContextHolder.setRequestAttributes(requestAttributes);

很可能参考了一些博客的做法
在这里插入图片描述

但人家是等待所有异步线程结束才返回,而这里的业务是直接返回,显然里面的头也就没有了也没有任何作用,并且导致了取到了空对象的上下文。
同时,也需要排查下框架中有无全局设置RequestContextHolder.setRequestAttributes(requestAttributes,true);的地方,因为这个的作用等同于在异步线程设置requestAttributes

结束

所以看问题 早看源码早胜利 加油

最后

以上就是花痴香烟为你收集整理的OpenFeign异步线程调用丢失请求头问题排查记录前言分析寻找解决途径的全部内容,希望文章能够帮你解决OpenFeign异步线程调用丢失请求头问题排查记录前言分析寻找解决途径所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部