最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解feign調(diào)用session丟失解決方案

 更新時(shí)間:2019年02月18日 15:32:35   作者:zl1zl2zl3  
這篇文章主要介紹了詳解feign調(diào)用session丟失解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

最近在做項(xiàng)目的時(shí)候發(fā)現(xiàn),微服務(wù)使用feign相互之間調(diào)用時(shí),存在session丟失的問題。例如,使用Feign調(diào)用某個(gè)遠(yuǎn)程API,這個(gè)遠(yuǎn)程API需要傳遞一個(gè)鑒權(quán)信息,我們可以把cookie里面的session信息放到Header里面,這個(gè)Header是動態(tài)的,跟你的HttpRequest相關(guān),我們選擇編寫一個(gè)攔截器來實(shí)現(xiàn)Header的傳遞,也就是需要實(shí)現(xiàn)RequestInterceptor接口,具體代碼如下:

@Configuration 
@EnableFeignClients(basePackages = "com.xxx.xxx.client") 
public class FeignClientsConfigurationCustom implements RequestInterceptor { 
 
 @Override 
 public void apply(RequestTemplate template) { 
 
  RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); 
  if (requestAttributes == null) { 
   return; 
  } 
 
  HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); 
  Enumeration<String> headerNames = request.getHeaderNames(); 
  if (headerNames != null) { 
   while (headerNames.hasMoreElements()) { 
    String name = headerNames.nextElement(); 
    Enumeration<String> values = request.getHeaders(name); 
    while (values.hasMoreElements()) { 
     String value = values.nextElement(); 
     template.header(name, value); 
    } 
   } 
  } 
 
 } 
 
} 

經(jīng)過測試,上面的解決方案可以正常的使用; 

但是,當(dāng)引入Hystrix熔斷策略時(shí),出現(xiàn)了一個(gè)新的問題:

RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

此時(shí)requestAttributes會返回null,從而無法傳遞session信息,最終發(fā)現(xiàn)RequestContextHolder.getRequestAttributes(),該方法是從ThreadLocal變量里面取得對應(yīng)信息的,這就找到問題原因了,是由于Hystrix熔斷機(jī)制導(dǎo)致的。 
Hystrix有2個(gè)隔離策略:THREAD以及SEMAPHORE,當(dāng)隔離策略為 THREAD 時(shí),是沒辦法拿到 ThreadLocal 中的值的。

因此有兩種解決方案:

方案一:調(diào)整格隔離策略:

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

這樣配置后,F(xiàn)eign可以正常工作。

但該方案不是特別好。原因是Hystrix官方強(qiáng)烈建議使用THREAD作為隔離策略! 可以參考官方文檔說明。

方案二:自定義策略

記得之前在研究zipkin日志追蹤的時(shí)候,看到過Sleuth有自己的熔斷機(jī)制,用來在thread之間傳遞Trace信息,Sleuth是可以拿到自己上下文信息的,查看源碼找到了 
org.springframework.cloud.sleuth.instrument.hystrix.SleuthHystrixConcurrencyStrategy 
這個(gè)類,查看SleuthHystrixConcurrencyStrategy的源碼,繼承了HystrixConcurrencyStrategy,用來實(shí)現(xiàn)了自己的并發(fā)策略。

/**
 * Abstract class for defining different behavior or implementations for concurrency related aspects of the system with default implementations.
 * <p>
 * For example, every {@link Callable} executed by {@link HystrixCommand} will call {@link #wrapCallable(Callable)} to give a chance for custom implementations to decorate the {@link Callable} with
 * additional behavior.
 * <p>
 * When you implement a concrete {@link HystrixConcurrencyStrategy}, you should make the strategy idempotent w.r.t ThreadLocals.
 * Since the usage of threads by Hystrix is internal, Hystrix does not attempt to apply the strategy in an idempotent way.
 * Instead, you should write your strategy to work idempotently. See https://github.com/Netflix/Hystrix/issues/351 for a more detailed discussion.
 * <p>
 * See {@link HystrixPlugins} or the Hystrix GitHub Wiki for information on configuring plugins: <a
 *  rel="external nofollow" >https://github.com/Netflix/Hystrix/wiki/Plugins</a>.
 */
public abstract class HystrixConcurrencyStrategy 

搜索發(fā)現(xiàn)有好幾個(gè)地方繼承了HystrixConcurrencyStrategy類 

其中就有我們熟悉的Spring Security和剛才提到的Sleuth都是使用了自定義的策略,同時(shí)由于Hystrix只允許有一個(gè)并發(fā)策略,因此為了不影響Spring Security和Sleuth,我們可以參考他們的策略實(shí)現(xiàn)自己的策略,大致思路: 

將現(xiàn)有的并發(fā)策略作為新并發(fā)策略的成員變量; 

在新并發(fā)策略中,返回現(xiàn)有并發(fā)策略的線程池、Queue; 

代碼如下:

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

最后,將這個(gè)策略類作為bean配置到feign的配置類FeignClientsConfigurationCustom中

 @Bean
 public FeignHystrixConcurrencyStrategy feignHystrixConcurrencyStrategy() {
  return new FeignHystrixConcurrencyStrategy();
 }

至此,結(jié)合FeignClientsConfigurationCustom配置feign調(diào)用session丟失的問題完美解決。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。 

相關(guān)文章

  • 教你用Java Swing實(shí)現(xiàn)自助取款機(jī)系統(tǒng)

    教你用Java Swing實(shí)現(xiàn)自助取款機(jī)系統(tǒng)

    今天給大家?guī)淼氖顷P(guān)于JAVA的相關(guān)知識,文章圍繞著如何用Java Swing實(shí)現(xiàn)自助取款機(jī)系統(tǒng)展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • Java前端開發(fā)框架實(shí)現(xiàn)的流程和代碼示例

    Java前端開發(fā)框架實(shí)現(xiàn)的流程和代碼示例

    我們可以實(shí)現(xiàn)一個(gè)Java前端開發(fā)框架,這個(gè)框架包含了初始化、組件渲染、組件更新、事件監(jiān)聽和事件觸發(fā)等功能,希望這個(gè)指南能夠?qū)側(cè)胄械男“子兴鶐椭?/div> 2023-10-10
  • Java設(shè)計(jì)模式之策略模式深入刨析

    Java設(shè)計(jì)模式之策略模式深入刨析

    策略模式屬于Java 23種設(shè)計(jì)模式中行為模式之一,該模式定義了一系列算法,并將每個(gè)算法封裝起來,使它們可以相互替換,且算法的變化不會影響使用算法的客戶。本文將通過示例詳細(xì)講解這一模式,需要的可以參考一下
    2022-05-05
  • ssm?mybatis如何配置多個(gè)mapper目錄

    ssm?mybatis如何配置多個(gè)mapper目錄

    這篇文章主要介紹了ssm?mybatis如何配置多個(gè)mapper目錄,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教。
    2022-01-01
  • Spring?容器初始化?register?與?refresh方法

    Spring?容器初始化?register?與?refresh方法

    這篇文章主要介紹了Spring?容器初始化?register?與?refresh方法,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-07-07
  • SpringBoot常用計(jì)量與bean屬性校驗(yàn)和進(jìn)制數(shù)據(jù)轉(zhuǎn)換規(guī)則全面分析

    SpringBoot常用計(jì)量與bean屬性校驗(yàn)和進(jìn)制數(shù)據(jù)轉(zhuǎn)換規(guī)則全面分析

    這篇文章主要介紹了SpringBoot常用計(jì)量、bean屬性校驗(yàn)與進(jìn)制數(shù)據(jù)轉(zhuǎn)換規(guī)則,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-10-10
  • Java在PowerPoint幻燈片中創(chuàng)建散點(diǎn)圖的方法

    Java在PowerPoint幻燈片中創(chuàng)建散點(diǎn)圖的方法

    散點(diǎn)圖是通過兩組數(shù)據(jù)構(gòu)成多個(gè)坐標(biāo)點(diǎn),考察坐標(biāo)點(diǎn)的分布,判斷兩變量之間是否存在某種關(guān)聯(lián)或總結(jié)坐標(biāo)點(diǎn)的分布模式,這篇文章主要介紹了Java如何在PowerPoint幻燈片中創(chuàng)建散點(diǎn)圖,需要的朋友可以參考下
    2023-04-04
  • 排序算法的Java實(shí)現(xiàn)全攻略

    排序算法的Java實(shí)現(xiàn)全攻略

    這篇文章主要介紹了排序算法的Java實(shí)現(xiàn),包括Collections.sort()的使用以及各種經(jīng)典算法的Java代碼實(shí)現(xiàn)方法總結(jié),超級推薦!需要的朋友可以參考下
    2015-08-08
  • SpringBoot security安全認(rèn)證登錄的實(shí)現(xiàn)方法

    SpringBoot security安全認(rèn)證登錄的實(shí)現(xiàn)方法

    這篇文章主要介紹了SpringBoot security安全認(rèn)證登錄的實(shí)現(xiàn)方法,也就是使用默認(rèn)用戶和密碼登錄的操作方法,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • Spring中存對象和取對象的方式詳解

    Spring中存對象和取對象的方式詳解

    這篇文章主要介紹了Spring中存對象和取對象的方式,Spring中更簡單的存對象與取對象的方式是注解,注解實(shí)現(xiàn)有兩種方式:一在編譯的時(shí)候,把注解替換成相關(guān)代碼,并添加到我們原來的代碼中,二攔截方法,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下
    2024-08-08

最新評論

静海县| 堆龙德庆县| 宁都县| 南平市| 周口市| 安仁县| 南投县| 西华县| 嘉鱼县| 锦州市| 肇州县| 朔州市| 错那县| 苍山县| 迭部县| 沈阳市| 敖汉旗| 子洲县| 贵定县| 蒙阴县| 瑞安市| 专栏| 长宁县| 霞浦县| 潍坊市| 屏山县| 龙陵县| 云霄县| 璧山县| 马关县| 公安县| 聂拉木县| 铜陵市| 南靖县| 渭源县| 西畴县| 乐亭县| 莆田市| 曲周县| 迁安市| 昂仁县|