- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
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类 。
其中就有我们熟悉的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的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
有什么区别: spring-cloud-starter-openfeign ( https://github.com/spring-cloud/spring-cloud-openfeign ) 和 s
我们正在使用netflix feign来调用 Restful Web服务。对于补丁请求,看来不支持PATCH请求。 Caused by: feign.RetryableException: Inval
据我了解,当请求响应状态码!= 2xx 时,将调用 feign ErrorDecoder 的 decode() 方法。通过调试我的测试,我发现我的 CustomErrorDecoder 的 decod
我有一个像这样构建的假客户端服务: Feign.Builder builder = Feign.builder() .contract(new SpringMvcContract())
使用spring cloud feign调用我的服务,当服务返回401异常时,respose.body()一片空白。 当我抛出异常时 throw new BadRequestException(400
我使用 ErrorDecoder 返回正确的异常而不是 500 状态代码。 有没有办法在解码器中检索原始消息。我可以看到它在 FeignException 中,但不在 decode 方法中。我所拥有的
通过学习曲线,遇到了这个场景: 鉴于90%的调用都是JSON,在构建客户端时添加了GSON解码器。不过接口(interface)中有些方法调用应该是支持raw return without decod
我正在尝试使用以下 Feign 客户端在 Spring Boot 应用程序中检索在线图像内容。 @FeignClient(name = "image") public interface ImageC
我正在使用需要设置几个字段的 REST api。我的应用程序应始终将某些字段设置为相同的值。是否可以在带有 feign 定义(或其他地方)的界面中使这些值“硬编码”? 我的假声明看起来像这个例子。假设
我是新来的 Spring 和假装和探索几天以来。我能够向我们的 protected 资源(用户名/密码)发出身份验证请求,并在后续请求 header 中使用身份验证服务返回的 JWT token 。但
我尝试在我的 Spring Boot 应用程序上配置 OpenFeign,我使用 pokeapi 进行测试。 我编写了这段代码: @FeignClient(value = "pokeapi", url
快速浏览了Feign的源码,发现Feign使用的是JDK的HttpUrlConnection在不使用连接池的情况下发出 HTTP 请求并在请求完成时关闭它。我怀疑这种方式的效率。然后我看了Spring
我为 feignClients 启用了我的 spring 云,如下所示: @Configuration @EnableAutoConfiguration @RestController @Enable
当我发帖时 Map使用 Feign Client,我收到错误消息: feign.FeignException: status 400 reading MAp . 代码 //Client side @C
目录 使用HttpClient和OkHttp 使用HttpClient 使用OkHttp OpenFeign替换为OkHtt
需求 最近小编的项目中出现了很多feign 调用出现 Read Time out 的异常,但因为没有集成链路追踪的第三方框架,查不到原因。 所以想到打印请求的ip地址,判断是指定的服务器出现的问
我正在使用 spring feign 压缩请求和响应 服务器端: server: servlet: context-path: /api/v1/ compression: en
我面临以下情况,令我惊讶的是,我找不到太多文档:有一项服务仅通过一一获取项目详细信息来提供休息调用。总共有 1000 多个项目。 出于响应能力的原因,我想将这些数据保留在我的一端,而不是懒惰地获取它。
我正在尝试实现一个涉及 FeignClient 调用的单元测试,该调用应返回 404 Not Found。 由于 Feign 抛出了 404 异常,那么实现此测试用例的正确方法是什么? 我正在尝试这样
当使用spring-cloud-feign连接到本地主机时,Feign找不到url,而是给我以下错误消息。 2019-11-13 12:01:55.553 ERROR 23798 --- [n
我是一名优秀的程序员,十分优秀!