Feign请求头丢失的解决方法及其分析

发现问题

在写多服务互相调用的时候,发现远程feign调用方法正常情况下是无法将请求头的信息(例如token等)顺带传播的。

我们可以添加远程 feign 远程调用拦截器,来获取token 数据。
在这里插入图片描述

如上图:因为微服务之间并没有传递头文件,所以我们可以定义一个拦截器,每次微服务调用之前都先检查下头文件,将请求的头文件中的用户信息再放入到header中,再调用其他微服务即可。

package com.atguigu.tingshu.common.feign;import feign.RequestInterceptor;
import feign.RequestTemplate;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;@Component
public class FeignInterceptor implements RequestInterceptor {public void apply(RequestTemplate requestTemplate){//  获取请求对象RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();if(null != requestAttributes) {ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)requestAttributes;HttpServletRequest request = servletRequestAttributes.getRequest();String token = request.getHeader("token");requestTemplate.header("token", token);}}
}

我们再次清晰地梳理一下feign请求头丢失的问题:

原因:每次feign进行远程调用,会new一个新的Request,并发出去。不会看以前的老请求。

解决:利用拦截器;每次发请求之前。把老请求的请求头获取到放到RequestTemplate中,保证RequestTemplate有头信息就行。

PS:

同一个线程期间共享数据

  • Map<Thread,数据>: 手动移除
  • ThreadLocal<数据>: 可自动,推荐手动
  • RequestContextHolder
    • 请求上下文。能获取到之前的老请求; 原理ThreadLocal机制,把用户信息隐式传参下去。

feign进行远程调用的源码分析

对feign整体流程的分析。

  • 我们编写feignclient接口,SpringBoot容器启动会扫描每个接口并生成代理对象放在容器中
  • 自动注入feign接口类,会拿到它的代理对象; ReflectiveFeign.FeignInvocationHandler

1、SpringBoot启动扫描每个feign接口,并创建ReflectiveFeign 代理对象

2、并且把feign接口的每个方法,用什么处理器执行,提前保存起来

Map<Method, MethodHandler> dispatch;

​ 当前方法对应的MethodHandler是 SynchronousMethodHandler

3、远程调用流程是在: SynchronousMethodHandler.invoke(); 方法详细如下

  public Object invoke(Object[] argv) throws Throwable {RequestTemplate template = buildTemplateFromArgs.create(argv);Options options = findOptions(argv);Retryer retryer = this.retryer.clone();while (true) {try {return executeAndDecode(template, options);} catch (RetryableException e) {try {retryer.continueOrPropagate(e);} catch (RetryableException th) {Throwable cause = th.getCause();if (propagationPolicy == UNWRAP && cause != null) {throw cause;} else {throw th;}}if (logLevel != Logger.Level.NONE) {logger.logRetry(metadata.configKey(), logLevel);}continue;}}}

详细流程:

  • 1、创建请求模板; 封装准备要发送的请求的完整数据(注意观察,头里面没东西);新new的

    • 在这里插入图片描述
  • 2、发现参数位置是否有连接超时等设置参数。(我们没有,连接超时都是统一配置)

    • 允许我们通过传参的方式精确调整每个请求的超时时间

    • //声明
      @GetMapping("/add/{Id}/{num}")Result<SkuInfo> addToCart(@PathVariable("Id") Long id,@PathVariable("num") Integer num,Request.Options options);//调用
      Request.Options options = new Request.Options(1000,2000);
      Result<Thing> result = testFeignClient.addThing(id, num,options);
      
  • 3、获取重试器: 利用while(true),判断重试器如果抛了异常,while炸掉就不重试,重试器没抛异常,while就会continue

    • while (true) {try {//真正执行远程调用return executeAndDecode(template, options);} catch (RetryableException e) {try {retryer.continueOrPropagate(e);} catch (RetryableException th) {Throwable cause = th.getCause();if (propagationPolicy == UNWRAP && cause != null) {throw cause;} else {throw th;}}if (logLevel != Logger.Level.NONE) {logger.logRetry(metadata.configKey(), logLevel);}continue;}}
      
  • 4、远程调用流程: executeAndDecode

    • 1、根据请求模板得到请求对象(注意观察,没头)

    • 2、client执行请求,开始远程调用

      • 1、找nacos要到需要调用的微服务的远程地址

      • 2、打开连接,发送请求

      • 在这里插入图片描述

      • 3、获取inputstream、outputstream数据

    • 3、把远程调用得到的json结果,利用decoder解码成方法希望的返回对象

feign是怎么进行远程调用

1、我们编写feign接口说清楚要调用哪个服务哪个地址@FeignClient

2、SpringBoot启动为每个接口创建代理对象

3、远程调用是代理对象在执行: 最终是 SynchronousMethodHandler帮我们远程调用

4、先解析各种参数;构造出远程请求对象。(请求方式、请求路径、请求参数、请求头)

5、利用LoadBalancerFeignClient负载均衡客户端先去nacos拿到对方微服务的所有地址

​ 有缓存机制,如果以前调用过,其他被调用过的服务的 FeignLoadBalancer 会被缓存起来

6、根据这个地址构造出URL。然后openConnection();打开连接准备收发数据

7、用connection的outputstream把我们要发出去的数据写出去

8、用connection的inputstream感知对方给我们响应的数据

9、利用decoder把对方响应给我们的数据,逆转为方法的返回值类型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/453732.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

两次NAT

两次NAT即Twice NAT&#xff0c;指源IP和目的IP同时转换&#xff0c;该技术应用于内部网络主机地址与外部网络上主机地址重叠的情况。 如图所示&#xff0c;两次NAT转换的过程如下: 内网Host A要访问地址重叠的外部网络Host B&#xff0c;Host A向位于外部网络的DNS服务器发送…

SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式 基础(持续更新~)

具体操作&#xff1a; day2: 作用&#xff1a; 出现跨域问题 配相对应进行配置即可解决&#xff1a; IDEA连接的&#xff0c;在url最后加参数?useSSLfalse注意链接密码是123&#xff08;docker中mysql密码&#xff09; 注意&#xff0c;虚拟机中设置的密码和ip要和主机上…

vue2使用echarts自定义tooltip内容

先上最终效果图 # 实现过程&#xff1a; 一、下载引入echarts 下载 npm install echarts --save在main.js中引入 import * as echarts from "echarts"; Vue.prototype.$echarts echarts;二、使用 <template><div id"myechart" style"…

神经网络激活函数到底是什么?

激活函数 其实不是很难啦&#xff0c;归结一下就是大概这样几个分类&#xff0c;详情请参考【神经网络】大白话直观理解&#xff01;_哔哩哔哩_bilibili神经网络就是干这个事的~ 如果队伍不长&#xff0c;一个ykxb就可以了&#xff0c;如果 如果 队伍太长 就加一个激活函数也…

前端开发之deepmerge的使用和示例(对象的深度合并)

前端开发之deepmerge的使用和示例 前言使用场景链接效果图vue中简单案例1、安装插件2、示例结果 前言 在平时的项目中经常会涉及到对象除了第一层以及下层进行深度合并&#xff0c;本问讲解的是深度合并的插件deepmerge&#xff0c;使用此插件避免通过递归实现一些深度合并所带…

新手指南:Postman 旧版本(历史版本)下载

随着技术的不断发展&#xff0c;有时候我们发现自己需要退回到使用 Postman 某个以往的版本。这篇文章旨在指导你如何安全地移除当前版本的 Postman、查找并获取旧版本。 从你的系统中移除 Postman 为了确保旧版本的 Postman 可以无障碍地安装&#xff0c;首先得从你的系统中…

LlamaIndex 入门实战

文章目录 LlamaIndex 入门实战1. 基本概念2. 优劣势分析3. 简单代码示例4. Index持久化5. 使用场景6. 总结 LlamaIndex 入门实战 LlamaIndex是一个连接大型语言模型&#xff08;LLMs&#xff09;与外部数据的工具&#xff0c;它通过构建索引和提供查询接口&#xff0c;使得大模…

超低价搭建cyberpanel+LiteSpeed企业版web服务器

注意&#xff0c;这里的企业版使用的是官方提供的免费密钥&#xff0c;在密钥激活后有一个月的有效时间&#xff0c;到期后官方会自动续期你的密钥 教学用配置&#xff1a; image1097698 126 KB 优惠链接&#xff1a;雨云 - 新一代云服务提供商 3 这是LiteSpeed&#xff08;以…

迷你洗衣机什么牌子好?口碑好的迷你洗衣机

在日常生活中&#xff0c;内衣洗涤是大多人都比较头疼的问题&#xff0c;看似一件小小的衣物&#xff0c;可是程序繁杂&#xff0c;洗涤、消毒一样不能少&#xff0c;每天都要占用我们大量的时间&#xff0c;而传统的大型洗衣机又无法满足对内衣洗护的特殊需求&#xff0c;所以…

k8s学习-Kubernetes的网络

Kubernetes作为编排引擎管理着分布在不同节点上的容器和Pod。Pod、Service、外部组件之间需要⼀种可靠的方找到彼此并进行通信&#xff0c;Kubernetes网络则负责提供这个保障。 1.1 Kubernetes网络模型 Container-to-Container的网络 当Pod被调度到某个节点&#xff0c;Pod中…

Windows Server 2019 DNS服务器搭建

系列文章目录 目录 系列文章目录 文章目录 前言 一、DNS服务器是什么&#xff1f; 二、配置服务器 1.实验环境搭建 1)实验服务器配置和客户端 2)实验环境 2.服务器配置 正向解析配置 反向解析 实验验证 文章目录 Windows Server 2003 Web服务器搭建Windows Server…

Python算法题集_相交链表

Python算法题集_相交链表 题41&#xff1a;相交链表1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【双层循环】2) 改进版一【双指针】3) 改进版二【哈希检索-集合】4) 改进版三【哈希检索-字典】 本文为Python算法题集之一的代码示例 题41&am…