微服务中 Feign调用以及网关Zuul的请求头相关问题

在Spring Cloud的微服务架构中,Feign调用可能出现请求头丢失问题,主要原因是Hystrix的隔离策略。解决方案包括自定义并发策略和FeignInterceptor。Zuul作为网关,可以通过RequestContext处理请求头的添加、修改和过滤。
摘要由CSDN通过智能技术生成

微服务中 Feign调用以及网关Zuul的请求头与字段相关问题

前言

在Spring Cloud中使用Feign进行远端调用时,会发生请求头信息的丢失,下游服务无法获取到上游服务请求头的问题。在搭配Zuul网关后,可能会需要使用前置过滤器对上游服务的请求头信息进行修改、添加或过滤 再转至下游服务。

1. Feign远程调用请求头丢失

在不进行任何配置的请求下,Feign在进行远程调用的时候,会发现下游服务无法获取到上游服务发送的请求头,而在许多时候,请求头包含了一些重要信息,如 关联性ID、授权认证等等。

1.1 原因分析

Feign发起远程调用,实际上是通过@HystrixCommand命令去发起的,而了解Hystrix的调用隔离策略可知,Hsyrix有两种隔离策略,一种SEMAPHORE(信号量)这是一个轻量级的隔离策略,当上游服务发生远程调用时,会直接在原调用线程中直接发起;另一种Thread(线程)这是一个默认的隔离策略,也是Hystrix官方大力推荐地策略,使用THREAD策略会另起一个子线程来进行远程调用,这样远程调用可能发生的错误或异常也不会想到原调用线程。

引起下游服务无法接收到请求头信息的原因有二:其一,在上游服务接收到请求头新信息之后,并没有把请求头信息再封装到远程调用的request中,这里可以通过加入一个拦截器FeignInterceptor来添加;其二,即使添加了FeignInterceptor也会发现下游服务依然无法获取到请求头信息,这是由于 FeignInterceptor中,在封装请求头信息到request的时候就已经丢失了,在获取请求头信息时,一般是通过 RequestContextHolder进行获取的,而这个类会将RequestContext请求上下文封装到ThreadLocal中以供使用,而由于Hystrix的默认隔离策略,子线程与父线程之间是无法传递ThreadLocal对象的

1.2 解决方案1

知道了原因就可以有两个解决方案,最简单粗暴但不推荐的就是改变Hystrix的隔离策略,将默认的Thread策略改为SEMAPHORE策略,但是既然官方极力不推荐这种,也只做了解吧。

① FeignInterceptor拦截器,添加需要转发的请求头信息

/**
 * @Author: Jam
 * @Date: 2020/5/30 13:12
 */
@Component
public class FeignInterceptor implements RequestInterceptor {
   
    @Override
    public void apply(RequestTemplate template) {
   
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
   
            HttpServletRequest request = attributes.getRequest();
            //header消息传递 本文示例 传递四个请求头信息
            template.header("tmx-correlation-id",request.getHeader("tmx-correlation-id"));
            template.header("tmx-auth-token",request.getHeader("tmx-auth-token"));
            template.header"tmx-user-id",request.getHeader("tmx-user-id"));
            template.header("tmx-org-id",request.getHeader("tmx-org-id"));
        }
    }
}

② 修改@HystrixCommand的执行策略

@HyscrixCommand(commandProperties={
   @HysrixProperty(name="execution.isolation.strategy",value="SEMAPHORE")})
public void RemoteCall(){
   
    return feignClient.get();
}

以上为通过修改Hystrix的隔离策略为SEMAHORE来解决Feign调用中无法传递请求头。但不推荐,不推荐,不推荐!

1.3 解决方案2

为了使用Thread策略来执行Hystrix调用,那么就要将父线程(原调用线程)的RequestContext传递到子线程中,Hystrix提供了并发策略机制,完成上下文的传播,所以只要通过自定义并发策略 就可以让子线程获得请求头信息。tips:Hystrix只允许一个并发策略,所以自定义并发策略时,原先会存在一个用以处理安全的并发策略,所以要把他们进行合并。

① 自定义并发策略FeignConfig,继承HystrixConcurrencyStrategy类

@Component
public class FeignConfig extends 
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值