IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> OpenFeign异步线程调用丢失请求头问题排查记录 -> 正文阅读

[Java知识库]OpenFeign异步线程调用丢失请求头问题排查记录

作者:recommend-box insert-baidu-box

前言

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

分析

看这个报错提示,能看出来是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

结束

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

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-29 11:57:32  更:2022-04-29 11:58:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:52:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码