当前位置: 首页 > news >正文

OpenFeign:服务间通讯携带 Token 的实现

深入探讨:异步调用和MQ消费者场景下请求上下文缺失问题及解决方案

在微服务开发过程中,我们常常会遇到各种复杂的场景,其中异步调用和MQ消费者场景下的请求上下文缺失问题,是一个值得深入探讨的技术点。本文将结合具体的代码示例,详细分析这两个场景下问题产生的原因,并给出相应的解决方案。

一、背景引入

在微服务架构中,我们使用OpenFeign实现服务间的HTTP通信。为了确保服务间通信的安全性,通常需要在请求头中携带诸如token等认证信息。以下是一个用于在Feign请求中添加token的拦截器配置类代码:

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;

/**
 * @author : 胡浩
 * @version 1.0
 * @description: Feign 配置类,用于在请求头中添加 Token
 * @date 2022/11/15 18:37
 */
@Configuration
public class FeignConfig implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate requestTemplate) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        requestTemplate.header("token", request.getHeader("token"));
    }
}

该代码通过RequestContextHolder获取当前请求的上下文,进而从HttpServletRequest对象中提取token,并添加到Feign的请求头中。然而,在异步调用和MQ消费者场景下,RequestContextHolder.getRequestAttributes()却会返回null,这就导致Feign调用无法携带必要的认证信息。

二、异步调用场景下的问题剖析

(一)问题原因

在异步编排过程中,RequestAttributes存储在ThreadLocal中。由于主线程的ThreadLocal变量不会自动传递给子线程,所以当我们在子线程中执行异步任务并调用Feign客户端时,拦截器无法获取到主线程的请求上下文,也就无法获取到原有的请求头信息,例如token。这就导致Feign调用缺失必要的认证信息,可能引发服务调用失败或权限不足等问题。

(二)解决方案

  1. 启用异步支持:在Spring Boot应用中,首先需要在配置类上添加@EnableAsync注解来启用异步支持。
  2. 手动传递上下文:由于Spring的@Async异步处理默认不会传递线程本地变量,所以我们需要手动将父线程的上下文传递给子线程。可以通过以下代码实现:
ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
RequestContextHolder.setRequestAttributes(sra, true);

这里的第二个参数true表示该属性是可继承的,这样设置后,子线程就能够访问到父线程的请求属性,从而在Feign调用时可以正确携带token等信息。

三、MQ消费者场景下的问题剖析

(一)问题原因

当消息队列的消费者处理消息时,通常是在一个独立的线程中执行的。这个线程并非由HTTP请求触发,因此不存在与HTTP请求关联的RequestAttributes。所以,RequestContextHolder无法获取到原有的请求上下文,导致Feign调用时无法携带token等信息。这就使得MQ消费者在调用其他服务时,可能因为缺少认证信息而无法正常访问受保护的接口。

(二)解决方案

  1. 手动设置请求上下文:在消费者处理消息的逻辑中,手动设置请求上下文。可以从消息体中提取必要的信息,构建一个模拟的请求上下文,并将其设置到RequestContextHolder中。
  2. 在消息体中包含认证信息:在发送消息时,将必要的认证信息,如token,包含在消息体中。这样在消费者处理消息并进行Feign调用时,可以直接从消息体中获取认证信息,并添加到Feign请求头中。

四、总结

无论是异步调用还是MQ消费者场景,出现请求上下文缺失问题的根本原因在于ThreadLocal的线程隔离特性。这一特性使得在跨线程或非HTTP请求触发的场景下,无法自动获取上下文。为了解决这一问题,我们需要在这些场景中手动处理上下文的传递或设置,确保Feign调用能够正确携带所需的请求头信息,从而保证微服务间通信的安全性和稳定性。通过对这些问题的深入理解和有效解决,我们能够更好地构建健壮的微服务架构应用。

相关文章:

  • 本地大模型搭建与webui交互
  • 我和我的通义灵码
  • LeetCode:131. 分割回文串(DP Java)
  • 8 - PS XADC接口实验
  • Java 大视界 -- Java 大数据机器学习模型的可解释性增强技术与应用(107)
  • nist关于rsa中p,q的要求
  • 【数据挖掘】Pandas
  • 【开源免费】基于SpringBoot+Vue.JS网络海鲜市场系统(JAVA毕业设计)
  • 看得见摸得着的AI:具身智能
  • 【Java】多线程篇
  • Ubuntu 下 nginx-1.24.0 源码分析 - ngx_fd_info
  • redis slaveof 命令 执行后为什么需要清库重新同步
  • 阿里云oss文件上传springboot若依java
  • 用C语言实现一个链表(四)
  • 深度学习原理与Pytorch实战
  • VS Code 如何搭建CC++开发环境
  • 【C语言】字符函数与字符串函数
  • 【动手实验】TCP半连接队列、全连接队列实战分析
  • 军事理论综合版参考答案
  • 计算机三级网络技术备考(3)
  • 腾讯网微信公众平台/采集站seo提高收录
  • 中企动力网站开发/赣州seo公司
  • wordpress建壁纸站/广告联盟app下载官网
  • 电子工程师资格证/抖音seo怎么做的
  • wordpress 类似博客/搜索引擎优化的核心本质
  • 用织梦做网站费用/什么软件可以刷网站排名