feign远程调用方法时,请求需要携带信息的问题

最近在写一个业务,结合feign远程调用和spring security,再发送请求的时候需在请求头中加入身份信息。而另一个服务,需要这份身份信息,来获取id,不然就会报错,这里我用jwt存储身份信息。

首先写一个拦截器:

写一个拦截器,拦截下来feign的请求并添加所需要的信息。

由于这个拦截器是配置类,可以把他放置在公有的包里。

我这里的操作是:

拦截下来请求,并获取请求头,将请求头信息传入到feign的template中。

java 复制代码
@Slf4j
@Configuration
public class FeignInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate template) {
        //获取request对象
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if(requestAttributes != null){
            //获取request
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            //获取请求头
            String authorization = request.getHeader("Authorization");
            log.info("FeignInterceptor.apply authorization:{}",authorization);
            System.out.println("FeignInterceptor.apply authorization:{}"+authorization);
            //将请求头信息传递到feign中
            template.header("Authorization", authorization);
        }
    }
}

然后在对应的client里配置该类

报错:

正常来说,如果没有配置隔离策略,那么就可以正常对请求进行拦截了,但是如果feign结合了hystrix或者sentinel的线程隔离的话,那么就会获取不到。

源码剖析

RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

这个方法,是从上下文中获取内容

getRequestAttributes的方法是基于线程上下文实现的

ini 复制代码
	public static RequestAttributes getRequestAttributes() {
		RequestAttributes attributes = requestAttributesHolder.get();
		if (attributes == null) {
			attributes = inheritableRequestAttributesHolder.get();
		}
		return attributes;
	}

ThreadLocal:

arduino 复制代码
	private static final boolean jsfPresent =
			ClassUtils.isPresent("javax.faces.context.FacesContext", RequestContextHolder.class.getClassLoader());

	private static final ThreadLocal<RequestAttributes> requestAttributesHolder =
			new NamedThreadLocal<>("Request attributes");

	private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder =
			new NamedInheritableThreadLocal<>("Request context");

可以看出,他需要从本地线程中来获取。

对比一下hystrix和sentinel

Sentinel Hystrix
隔离策略 信号量隔离(限制每个服务线程请求数) 线程池隔离/信号量隔离(cpu性能降低)
熔断降级策略 基于慢调用比例(耗时比较久的熔断)或异常比例 基于失败比率
实时指标实现 滑动窗口 滑动窗口(基于 RxJava)
规则配置 支持多种数据源 支持多种数据源
扩展性 多个扩展点 插件的形式
基于注解的支持 支持 支持
限流 基于 QPS,支持基于调用关系的限流 有限的支持
流量整形 支持慢启动、匀速排队模式 不支持
系统自适应保护 支持 不支持
控制台 开箱即用,可配置规则、查看秒级监控、机器发现等 不完善
常见框架的适配 Servlet、Spring Cloud、Dubbo、gRPC 等 Servlet、Spring Cloud Netflix
yaml 复制代码
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 30000  #熔断超时时间

整合spring security的时候,远程调用接口想发送请求头信息,线程隔离的策略配置的是线程隔离。

由于在进行远程调用的时候,服务收到hystrix保护,在去调用的时候会去分配一些线程让该服务去执行,然后决定是否进行降级。而分配的这些线程是隔离的,也就是说无法访问本地线程的东西,因此在获取本地线程的请求头内容时返回为空,所以我们这里改成信号量隔离。采用更好的sentinel,它默认采用的是信号量隔离

在远程调用的时候获取不到请求头内容

解决

由于综合来看sentinel更为优秀,所以这里不去更改hystrix了,直接改用sentinel

更改feign配置

yaml 复制代码
feign:
  sentinel:
    enabled: true
  # hystrix:
  #   enabled: true
  circuitbreaker:
    enabled: true
# hystrix:
#   command:
#     default:
#       execution:
#         isolation:
#           thread:
#             timeoutInMilliseconds: 1000000  #熔断超时时间

就可以成功获取了。

相关推荐
阳光是sunny5 小时前
LangGraph中的Reducer是什么
前端·人工智能·后端
灯澜忆梦5 小时前
GO_并发编程---定时器
开发语言·后端·golang
阳光是sunny6 小时前
从链到图:LangGraph 入门基础全解析
前端·人工智能·后端
皮皮林5516 小时前
开源实力派,给本地 AI 装上深度调研能力,一张 3090 跑到 95.7 分!
后端
努力的小雨6 小时前
把 Windows 桌面图标做成一个会自己运转的小世界
后端
武子康7 小时前
Search Console Platform Properties 扩大 SEO 资产边界:从 Page Ranking 到 Topic Coverage(5 类误读边界 + 3 表数据层设计)
前端·人工智能·后端
腾渊信息科技公司8 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
IT_陈寒9 小时前
Vue这个特性差点让我加班到凌晨,谁懂啊
前端·人工智能·后端
段一凡-华北理工大学9 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化
码事漫谈10 小时前
1999年的电商前夜和2026年的AI前夜 历史押韵但从不重复
后端