微服务feign调用添加token
1.一般情况是这么配置的
具体的怎么调用就不说了 如下配置,就可以在请求头中添加需要的请求头信息。
- package localdate;
- import feign.RequestInterceptor;
- import feign.RequestTemplate;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.annotation.Configuration;
- 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;
- import javax.servlet.http.HttpServletRequest;
- import java.util.Collection;
- import java.util.Enumeration;
- import java.util.Iterator;
- import java.util.Map;
- /**
- * feign调用服务时,会丢失请求头信息。需要在这里把认证信息收到添加上去
- * @author TRON
- * @since 2019-11-23
- *
- *
- */
- @Configuration
- @Slf4j
- public class FeignTokenInterceptor implements RequestInterceptor {
- @Override
- public void apply(RequestTemplate requestTemplate) {
- log.info("======上下文中获取原请求信息======");
- String token = "without token";
- HttpServletRequest request = ((ServletRequestAttributes)
- RequestContextHolder.getRequestAttributes()).getRequest();
- Enumeration<String> headerNames = request.getHeaderNames();
- while (headerNames.hasMoreElements()) {
- String headerName = headerNames.nextElement();
- String HeadValue = request.getHeader(headerName);
- log.info("===原请求头信息=== headName: {}, headValue: {}", headerName, HeadValue);
- if (headerName.equals("X-Authorization-access_token")||headerName.equals("x-authorization-access_token")) {
- token = HeadValue;
- }
- }
- log.info("=======Feign添加头部信息start======");
- // requestTemplate.header("X-Authorization-access_token", token);
- requestTemplate.header("X-Authorization-access_token", "tron123456");
- log.info("=======Feign添加头部信息end======");
- }
- }
2 .但是,当熔断开启后,原先的这么配置就不起作用了
- package localdate;
- import com.netflix.hystrix.HystrixThreadPoolKey;
- import com.netflix.hystrix.strategy.HystrixPlugins;
- import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
- import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariable;
- import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableLifecycle;
- import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier;
- import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook;
- import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher;
- import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy;
- import com.netflix.hystrix.strategy.properties.HystrixProperty;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.context.request.RequestAttributes;
- import org.springframework.web.context.request.RequestContextHolder;
- import java.util.concurrent.BlockingQueue;
- import java.util.concurrent.Callable;
- import java.util.concurrent.ThreadPoolExecutor;
- import java.util.concurrent.TimeUnit;
- /**
- * 自定义并发策略
- * 将现有的并发策略作为新并发策略的成员变量
- * 在新并发策略中,返回现有并发策略的线程池、Queue
- *
- * hystrix.command.default.execution.isolation.strategy=THREAD
- * Hystrix的默认隔离策略(官方推荐,当使用该隔离策略时,是没办法拿到 ThreadLocal 中的值的,但是RequestContextHolder 源码中,使用了两个ThreadLocal)
- * hystrix.command.default.execution.isolation.strategy=SEMAPHORE (将隔离策略改为SEMAPHORE 也可以解决这个问题,但是官方并不推荐这个策略,因为这个策略对网络资源消耗比较大)
- *
- * 主要是解决当 Hystrix的默认隔离策略是THREAD时,不能通过RequestContextHolder获取到request对象的问题
- *
- */
- //@Configuration
- public class FeignConfig extends HystrixConcurrencyStrategy {
- private static final Logger log = LoggerFactory.getLogger(FeignConfig.class);
- private HystrixConcurrencyStrategy delegate;
- public FeignConfig() {
- try {
- this.delegate = HystrixPlugins.getInstance().getConcurrencyStrategy();
- if (this.delegate instanceof FeignConfig) {
- // Welcome to singleton hell...
- return;
- }
- HystrixCommandExecutionHook commandExecutionHook =
- HystrixPlugins.getInstance().getCommandExecutionHook();
- HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance().getEventNotifier();
- HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance().getMetricsPublisher();
- HystrixPropertiesStrategy propertiesStrategy =
- HystrixPlugins.getInstance().getPropertiesStrategy();
- this.logCurrentStateOfHystrixPlugins(eventNotifier, metricsPublisher, propertiesStrategy);
- HystrixPlugins.reset();
- HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
- HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook);
- HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);
- HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher);
- HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy);
- } catch (Exception e) {
- log.error("Failed to register Sleuth Hystrix Concurrency Strategy", e);
- }
- }
- private void logCurrentStateOfHystrixPlugins(HystrixEventNotifier eventNotifier,
- HystrixMetricsPublisher metricsPublisher, HystrixPropertiesStrategy propertiesStrategy) {
- if (log.isDebugEnabled()) {
- log.debug("Current Hystrix plugins configuration is [" + "concurrencyStrategy ["
- + this.delegate + "]," + "eventNotifier [" + eventNotifier + "]," + "metricPublisher ["
- + metricsPublisher + "]," + "propertiesStrategy [" + propertiesStrategy + "]," + "]");
- log.debug("Registering Sleuth Hystrix Concurrency Strategy.");
- }
- }
- @Override
- public <T> Callable<T> wrapCallable(Callable<T> callable) {
- RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
- return new WrappedCallable<>(callable, requestAttributes);
- }
- @Override
- public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey,
- HystrixProperty<Integer> corePoolSize, HystrixProperty<Integer> maximumPoolSize,
- HystrixProperty<Integer> keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
- return this.delegate.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, keepAliveTime,
- unit, workQueue);
- }
- @Override
- public BlockingQueue<Runnable> getBlockingQueue(int maxQueueSize) {
- return this.delegate.getBlockingQueue(maxQueueSize);
- }
- @Override
- public <T> HystrixRequestVariable<T> getRequestVariable(HystrixRequestVariableLifecycle<T> rv) {
- return this.delegate.getRequestVariable(rv);
- }
- static class WrappedCallable<T> implements Callable<T> {
- private final Callable<T> target;
- private final RequestAttributes requestAttributes;
- public WrappedCallable(Callable<T> target, RequestAttributes requestAttributes) {
- this.target = target;
- this.requestAttributes = requestAttributes;
- }
- @Override
- public T call() throws Exception {
- try {
- RequestContextHolder.setRequestAttributes(requestAttributes);
- return target.call();
- } finally {
- RequestContextHolder.resetRequestAttributes();
- }
- }
- }
- }
3 .feign和熔断的配置
- feign:
- client:
- config:
- default:
- connectTimeout: 5000 #连接超时3秒,连接失败时直接调用降级方法
- readTimeout: 100000 #连接成功,处理数据的时间限制10秒 100000 读取时间过短会抛异常java.net.SocketTimeoutException: Read timed out
- loggerLevel: full #日志输出等级
- hystrix:
- enabled: true
- hystrix:
- command:
- default:
- execution:
- isolation:
- thread:
- timeoutInMilliseconds: 5000 #服务连接成功,但是时间过长,降级方法调用时间 60000 5000
feign微服务的相互调用
我只是记录服务提供方、消费方的代码编写,配置什么的大家在网上搜,一大堆。
首先是服务提供方:
启动类上加上注解@EnableFeignClients,然后正常的写controller、service等业务逻辑
其次是服务的调用方:
1.首先启动类上加上注解@EnableFeignClients
2.编写服务调用接口
3.编写接口熔断处理方法
4.本人遇到的问题是需要用到调用方的请求头里面的信息,但是在提供方取不到,这时可以通过在调用方增加配置来解决
- import feign.RequestInterceptor;
- import feign.RequestTemplate;
- import java.util.Enumeration;
- import javax.servlet.http.HttpServletRequest;
- import org.springframework.web.context.request.RequestContextHolder;
- import org.springframework.web.context.request.ServletRequestAttributes;
- /**
- * @author ydf
- * @date 2021/5/13
- * @description:
- **/
- public class FeignBasicAuthRequestInterceptor implements RequestInterceptor {
- @Override
- public void apply(RequestTemplate requestTemplate) {
- ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
- .getRequestAttributes();
- HttpServletRequest request = attributes.getRequest();
- Enumeration<String> headerNames = request.getHeaderNames();
- if (headerNames != null) {
- while (headerNames.hasMoreElements()) {
- String name = headerNames.nextElement();
- String values = request.getHeader(name);
- requestTemplate.header(name, values);
- }
- }
- }
- }
- import com.jingling.netsign.applet.interceptor.FeignBasicAuthRequestInterceptor;
- import feign.RequestInterceptor;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- /**
- * @author ydf
- * @date 2021/5/13
- * @description:
- **/
- @Configuration
- public class FeignSupportConfig {
- /**
- * feign请求拦截器
- *
- * @return
- */
- @Bean
- public RequestInterceptor requestInterceptor(){
- return new FeignBasicAuthRequestInterceptor();
- }
- }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。
原文链接:https://blog.csdn.net/hzy3344520/article/details/105846487