解决微服务feign调用添加token的问题

时间:2022-10-07 21:15:05

微服务feign调用添加token

1.一般情况是这么配置的

具体的怎么调用就不说了 如下配置,就可以在请求头中添加需要的请求头信息。

  1. package localdate;
  2. import feign.RequestInterceptor;
  3. import feign.RequestTemplate;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.context.annotation.Configuration;
  7. import org.springframework.stereotype.Component;
  8. import org.springframework.web.context.request.RequestAttributes;
  9. import org.springframework.web.context.request.RequestContextHolder;
  10. import org.springframework.web.context.request.ServletRequestAttributes;
  11. import javax.servlet.http.HttpServletRequest;
  12. import java.util.Collection;
  13. import java.util.Enumeration;
  14. import java.util.Iterator;
  15. import java.util.Map;
  16. /**
  17. * feign调用服务时,会丢失请求头信息。需要在这里把认证信息收到添加上去
  18. * @author TRON
  19. * @since 2019-11-23
  20. *
  21. *
  22. */
  23. @Configuration
  24. @Slf4j
  25. public class FeignTokenInterceptor implements RequestInterceptor {
  26. @Override
  27. public void apply(RequestTemplate requestTemplate) {
  28. log.info("======上下文中获取原请求信息======");
  29. String token = "without token";
  30. HttpServletRequest request = ((ServletRequestAttributes)
  31. RequestContextHolder.getRequestAttributes()).getRequest();
  32. Enumeration<String> headerNames = request.getHeaderNames();
  33. while (headerNames.hasMoreElements()) {
  34. String headerName = headerNames.nextElement();
  35. String HeadValue = request.getHeader(headerName);
  36. log.info("===原请求头信息=== headName: {}, headValue: {}", headerName, HeadValue);
  37. if (headerName.equals("X-Authorization-access_token")||headerName.equals("x-authorization-access_token")) {
  38. token = HeadValue;
  39. }
  40. }
  41. log.info("=======Feign添加头部信息start======");
  42. // requestTemplate.header("X-Authorization-access_token", token);
  43. requestTemplate.header("X-Authorization-access_token", "tron123456");
  44. log.info("=======Feign添加头部信息end======");
  45. }
  46. }

2 .但是,当熔断开启后,原先的这么配置就不起作用了

  1. package localdate;
  2. import com.netflix.hystrix.HystrixThreadPoolKey;
  3. import com.netflix.hystrix.strategy.HystrixPlugins;
  4. import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
  5. import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariable;
  6. import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableLifecycle;
  7. import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier;
  8. import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook;
  9. import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher;
  10. import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy;
  11. import com.netflix.hystrix.strategy.properties.HystrixProperty;
  12. import org.slf4j.Logger;
  13. import org.slf4j.LoggerFactory;
  14. import org.springframework.context.annotation.Configuration;
  15. import org.springframework.web.context.request.RequestAttributes;
  16. import org.springframework.web.context.request.RequestContextHolder;
  17. import java.util.concurrent.BlockingQueue;
  18. import java.util.concurrent.Callable;
  19. import java.util.concurrent.ThreadPoolExecutor;
  20. import java.util.concurrent.TimeUnit;
  21. /**
  22. * 自定义并发策略
  23. * 将现有的并发策略作为新并发策略的成员变量
  24. * 在新并发策略中,返回现有并发策略的线程池、Queue
  25. *
  26. * hystrix.command.default.execution.isolation.strategy=THREAD
  27. * Hystrix的默认隔离策略(官方推荐,当使用该隔离策略时,是没办法拿到 ThreadLocal 中的值的,但是RequestContextHolder 源码中,使用了两个ThreadLocal)
  28. * hystrix.command.default.execution.isolation.strategy=SEMAPHORE (将隔离策略改为SEMAPHORE 也可以解决这个问题,但是官方并不推荐这个策略,因为这个策略对网络资源消耗比较大)
  29. *
  30. * 主要是解决当 Hystrix的默认隔离策略是THREAD时,不能通过RequestContextHolder获取到request对象的问题
  31. *
  32. */
  33. //@Configuration
  34. public class FeignConfig extends HystrixConcurrencyStrategy {
  35. private static final Logger log = LoggerFactory.getLogger(FeignConfig.class);
  36. private HystrixConcurrencyStrategy delegate;
  37. public FeignConfig() {
  38. try {
  39. this.delegate = HystrixPlugins.getInstance().getConcurrencyStrategy();
  40. if (this.delegate instanceof FeignConfig) {
  41. // Welcome to singleton hell...
  42. return;
  43. }
  44. HystrixCommandExecutionHook commandExecutionHook =
  45. HystrixPlugins.getInstance().getCommandExecutionHook();
  46. HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance().getEventNotifier();
  47. HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance().getMetricsPublisher();
  48. HystrixPropertiesStrategy propertiesStrategy =
  49. HystrixPlugins.getInstance().getPropertiesStrategy();
  50. this.logCurrentStateOfHystrixPlugins(eventNotifier, metricsPublisher, propertiesStrategy);
  51. HystrixPlugins.reset();
  52. HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
  53. HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook);
  54. HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);
  55. HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher);
  56. HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy);
  57. } catch (Exception e) {
  58. log.error("Failed to register Sleuth Hystrix Concurrency Strategy", e);
  59. }
  60. }
  61. private void logCurrentStateOfHystrixPlugins(HystrixEventNotifier eventNotifier,
  62. HystrixMetricsPublisher metricsPublisher, HystrixPropertiesStrategy propertiesStrategy) {
  63. if (log.isDebugEnabled()) {
  64. log.debug("Current Hystrix plugins configuration is [" + "concurrencyStrategy ["
  65. + this.delegate + "]," + "eventNotifier [" + eventNotifier + "]," + "metricPublisher ["
  66. + metricsPublisher + "]," + "propertiesStrategy [" + propertiesStrategy + "]," + "]");
  67. log.debug("Registering Sleuth Hystrix Concurrency Strategy.");
  68. }
  69. }
  70. @Override
  71. public <T> Callable<T> wrapCallable(Callable<T> callable) {
  72. RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
  73. return new WrappedCallable<>(callable, requestAttributes);
  74. }
  75. @Override
  76. public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey,
  77. HystrixProperty<Integer> corePoolSize, HystrixProperty<Integer> maximumPoolSize,
  78. HystrixProperty<Integer> keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
  79. return this.delegate.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, keepAliveTime,
  80. unit, workQueue);
  81. }
  82. @Override
  83. public BlockingQueue<Runnable> getBlockingQueue(int maxQueueSize) {
  84. return this.delegate.getBlockingQueue(maxQueueSize);
  85. }
  86. @Override
  87. public <T> HystrixRequestVariable<T> getRequestVariable(HystrixRequestVariableLifecycle<T> rv) {
  88. return this.delegate.getRequestVariable(rv);
  89. }
  90. static class WrappedCallable<T> implements Callable<T> {
  91. private final Callable<T> target;
  92. private final RequestAttributes requestAttributes;
  93. public WrappedCallable(Callable<T> target, RequestAttributes requestAttributes) {
  94. this.target = target;
  95. this.requestAttributes = requestAttributes;
  96. }
  97. @Override
  98. public T call() throws Exception {
  99. try {
  100. RequestContextHolder.setRequestAttributes(requestAttributes);
  101. return target.call();
  102. } finally {
  103. RequestContextHolder.resetRequestAttributes();
  104. }
  105. }
  106. }
  107. }

3 .feign和熔断的配置

  1. feign:
  2. client:
  3. config:
  4. default:
  5. connectTimeout: 5000 #连接超时3秒,连接失败时直接调用降级方法
  6. readTimeout: 100000 #连接成功,处理数据的时间限制10秒 100000 读取时间过短会抛异常java.net.SocketTimeoutException: Read timed out
  7. loggerLevel: full #日志输出等级
  8. hystrix:
  9. enabled: true
  10. hystrix:
  11. command:
  12. default:
  13. execution:
  14. isolation:
  15. thread:
  16. timeoutInMilliseconds: 5000 #服务连接成功,但是时间过长,降级方法调用时间 60000 5000

feign微服务的相互调用

我只是记录服务提供方、消费方的代码编写,配置什么的大家在网上搜,一大堆。

首先是服务提供方:

启动类上加上注解@EnableFeignClients,然后正常的写controller、service等业务逻辑

解决微服务feign调用添加token的问题

其次是服务的调用方:

1.首先启动类上加上注解@EnableFeignClients

解决微服务feign调用添加token的问题

2.编写服务调用接口

解决微服务feign调用添加token的问题

3.编写接口熔断处理方法

解决微服务feign调用添加token的问题

4.本人遇到的问题是需要用到调用方的请求头里面的信息,但是在提供方取不到,这时可以通过在调用方增加配置来解决

解决微服务feign调用添加token的问题

  1. import feign.RequestInterceptor;
  2. import feign.RequestTemplate;
  3. import java.util.Enumeration;
  4. import javax.servlet.http.HttpServletRequest;
  5. import org.springframework.web.context.request.RequestContextHolder;
  6. import org.springframework.web.context.request.ServletRequestAttributes;
  7.  
  8. /**
  9. * @author ydf
  10. * @date 2021/5/13
  11. * @description:
  12. **/
  13. public class FeignBasicAuthRequestInterceptor implements RequestInterceptor {
  14.  
  15. @Override
  16. public void apply(RequestTemplate requestTemplate) {
  17. ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
  18. .getRequestAttributes();
  19. HttpServletRequest request = attributes.getRequest();
  20. Enumeration<String> headerNames = request.getHeaderNames();
  21. if (headerNames != null) {
  22. while (headerNames.hasMoreElements()) {
  23. String name = headerNames.nextElement();
  24. String values = request.getHeader(name);
  25. requestTemplate.header(name, values);
  26. }
  27. }
  28. }
  29. }

解决微服务feign调用添加token的问题

  1. import com.jingling.netsign.applet.interceptor.FeignBasicAuthRequestInterceptor;
  2. import feign.RequestInterceptor;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. /**
  6. * @author ydf
  7. * @date 2021/5/13
  8. * @description:
  9. **/
  10. @Configuration
  11. public class FeignSupportConfig {
  12. /**
  13. * feign请求拦截器
  14. *
  15. * @return
  16. */
  17. @Bean
  18. public RequestInterceptor requestInterceptor(){
  19. return new FeignBasicAuthRequestInterceptor();
  20. }
  21. }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

原文链接:https://blog.csdn.net/hzy3344520/article/details/105846487