gpt4 book ai didi

详解feign调用session丢失解决方案

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 31 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章详解feign调用session丢失解决方案由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

最近在做项目的时候发现,微服务使用feign相互之间调用时,存在session丢失的问题。例如,使用feign调用某个远程api,这个远程api需要传递一个鉴权信息,我们可以把cookie里面的session信息放到header里面,这个header是动态的,跟你的httprequest相关,我们选择编写一个拦截器来实现header的传递,也就是需要实现requestinterceptor接口,具体代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@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);
     }
    }
   }
 
  }
 
}

经过测试,上面的解决方案可以正常的使用;  。

但是,当引入hystrix熔断策略时,出现了一个新的问题:

?
1
requestattributes requestattributes = requestcontextholder.getrequestattributes();

此时requestattributes会返回null,从而无法传递session信息,最终发现requestcontextholder.getrequestattributes(),该方法是从threadlocal变量里面取得对应信息的,这就找到问题原因了,是由于hystrix熔断机制导致的。  hystrix有2个隔离策略:thread以及semaphore,当隔离策略为 thread 时,是没办法拿到 threadlocal 中的值的.

因此有两种解决方案:

方案一:调整格隔离策略

?
1
hystrix.command. default .execution.isolation.strategy: semaphore

这样配置后,feign可以正常工作.

但该方案不是特别好。原因是hystrix官方强烈建议使用thread作为隔离策略! 可以参考官方文档说明.

方案二:自定义策略 。

记得之前在研究zipkin日志追踪的时候,看到过sleuth有自己的熔断机制,用来在thread之间传递trace信息,sleuth是可以拿到自己上下文信息的,查看源码找到了  org.springframework.cloud.sleuth.instrument.hystrix.sleuthhystrixconcurrencystrategy  这个类,查看sleuthhystrixconcurrencystrategy的源码,继承了hystrixconcurrencystrategy,用来实现了自己的并发策略.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
  * 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
  * href="https://github.com/netflix/hystrix/wiki/plugins" rel="external nofollow" >https://github.com/netflix/hystrix/wiki/plugins</a>.
  */
public abstract class hystrixconcurrencystrategy

搜索发现有好几个地方继承了hystrixconcurrencystrategy类  。

详解feign调用session丢失解决方案

其中就有我们熟悉的spring security和刚才提到的sleuth都是使用了自定义的策略,同时由于hystrix只允许有一个并发策略,因此为了不影响spring security和sleuth,我们可以参考他们的策略实现自己的策略,大致思路:  。

将现有的并发策略作为新并发策略的成员变量;  。

在新并发策略中,返回现有并发策略的线程池、queue;  。

代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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();
    }
   }
  }
}

最后,将这个策略类作为bean配置到feign的配置类feignclientsconfigurationcustom中 。

?
1
2
3
4
@bean
public feignhystrixconcurrencystrategy feignhystrixconcurrencystrategy() {
  return new feignhystrixconcurrencystrategy();
}

至此,结合feignclientsconfigurationcustom配置feign调用session丢失的问题完美解决.

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我。  。

原文链接:https://blog.csdn.net/zl1zl2zl3/article/details/79084368 。

最后此篇关于详解feign调用session丢失解决方案的文章就讲到这里了,如果你想了解更多关于详解feign调用session丢失解决方案的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com