<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Feign調(diào)用丟失Header的解決方案

          共 7190字,需瀏覽 15分鐘

           ·

          2020-12-06 16:54

          問(wèn)題

          在 Spring Cloud 中 微服務(wù)之間的調(diào)用會(huì)用到Feign,但是在默認(rèn)情況下,F(xiàn)eign 調(diào)用遠(yuǎn)程服務(wù)存在Header請(qǐng)求頭丟失問(wèn)題。

          解決方案

          首先需要寫(xiě)一個(gè) Feign請(qǐng)求攔截器,通過(guò)實(shí)現(xiàn)RequestInterceptor接口,完成對(duì)所有的Feign請(qǐng)求,傳遞請(qǐng)求頭和請(qǐng)求參數(shù)。

          Feign 請(qǐng)求攔截器

          public class FeignBasicAuthRequestInterceptor implements RequestInterceptor {

          private static final Logger logger = LoggerFactory.getLogger(FeignBasicAuthRequestInterceptor.class);

          @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);
          }
          }
          Enumeration<String> bodyNames = request.getParameterNames();
          StringBuffer body =new StringBuffer();
          if (bodyNames != null) {
          while (bodyNames.hasMoreElements()) {
          String name = bodyNames.nextElement();
          String values = request.getParameter(name);
          body.append(name).append("=").append(values).append("&");
          }
          }
          if(body.length()!=0) {
          body.deleteCharAt(body.length()-1);
          requestTemplate.body(body.toString());
          logger.info("feign interceptor body:{}",body.toString());
          }
          }
          }

          配置 讓所有?FeignClient,使用?FeignBasicAuthRequestInterceptor

          feign:
          client:
          config:
          default:
          connectTimeout: 5000
          readTimeout: 5000
          loggerLevel: basic
          requestInterceptors: com.leparts.config.FeignBasicAuthRequestInterceptor

          也可以配置讓 某個(gè)?FeignClient?使用這個(gè)?FeignBasicAuthRequestInterceptor

          feign:
          client:
          config:
          xxxx: # 遠(yuǎn)程服務(wù)名
          connectTimeout: 5000
          readTimeout: 5000
          loggerLevel: basic
          requestInterceptors: com.leparts.config.FeignBasicAuthRequestInterceptor

          經(jīng)過(guò)測(cè)試,上面的解決方案可以正常的使用;但是出現(xiàn)了新的問(wèn)題。

          在轉(zhuǎn)發(fā)Feign的請(qǐng)求頭的時(shí)候, 如果開(kāi)啟了Hystrix, Hystrix的默認(rèn)隔離策略是Thread(線程隔離策略), 因此轉(zhuǎn)發(fā)攔截器內(nèi)是無(wú)法獲取到請(qǐng)求的請(qǐng)求頭信息的。

          可以修改默認(rèn)隔離策略為信號(hào)量模式:

          hystrix.command.default.execution.isolation.strategy=SEMAPHORE

          但信號(hào)量模式不是官方推薦的隔離策略;另一個(gè)解決方法就是自定義Hystrix的隔離策略。

          自定義策略

          HystrixConcurrencyStrategy 是提供給開(kāi)發(fā)者去自定義hystrix內(nèi)部線程池及其隊(duì)列,還提供了包裝callable的方法,以及傳遞上下文變量的方法。所以可以繼承了HystrixConcurrencyStrategy,用來(lái)實(shí)現(xiàn)了自己的并發(fā)策略。

          @Component
          public class FeignHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {

          private static final Logger log = LoggerFactory.getLogger(FeignHystrixConcurrencyStrategy.class);

          private HystrixConcurrencyStrategy delegate;

          public FeignHystrixConcurrencyStrategy() {
          try {
          this.delegate = HystrixPlugins.getInstance().getConcurrencyStrategy();
          if (this.delegate instanceof FeignHystrixConcurrencyStrategy) {
          // 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 instance = HystrixPlugins.getInstance();
          instance.registerConcurrencyStrategy(this);
          instance.registerCommandExecutionHook(commandExecutionHook);
          instance.registerEventNotifier(eventNotifier);
          instance.registerMetricsPublisher(metricsPublisher);
          instance.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 ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey,
          HystrixThreadPoolProperties threadPoolProperties) {
          return this.delegate.getThreadPool(threadPoolKey, threadPoolProperties);
          }

          @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;

          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();
          }
          }
          }
          }

          致此,F(xiàn)eign調(diào)用丟失請(qǐng)求頭的問(wèn)題就解決的了 。

          參考

          https://blog.csdn.net/zl1zl2zl3/article/details/79084368
          https://cloud.spring.io/spring-cloud-static/spring-cloud-openfeign/2.2.0.RC2/reference/html/

          -- END --




          推薦閱讀:


          喜歡我可以給我設(shè)為星標(biāo)哦

          好文章,我“在看”


          瀏覽 26
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲成人资源网 | 最新日韩黄色电影网站 | 草青网在线 | 欧美性爱在线中文字幕 | 操逼莫熊|