我想转发带有假装客户端RequestInterceptor的请求标头,但在RequestInterceptor.apply
内,RequestContextHolder.getRequestAttributes()
为null
,SecurityContextHolder.getContext().getAuthentication()
也是hystrix.command.default.execution.isolation.strategy: SEMAPHORE
(我最终也可以得到我的标题的价值。)
这在升级到Spring-Cloud Brixton之前已经工作了,其中hystrix命令现在必须可以在一个单独的线程中运行,因为更改为以下参数可以解决问题:
if (DBNull.Value.Equals(row["Effect_Date_From"]))
{
// null
}
现在,我不太热衷于更改此类默认值,如果没有必要,是否还有另一种推荐的转发标头方式?
由于
答案 0 :(得分:4)
对于Spring Boot 2+ / Spring Cloud Finchley +,如果您只需要安全上下文,则可以设置以下属性:
hystrix.shareSecurityContext=true
请求拦截器应该可以工作。
对于其他用例或早期版本(非常感谢Spring Cloud Sleuth的灵感):
“所有”你要做的就是实现一个HystrixConcurrencyStrategy
,每当有一个线程发生变化时都会传递信息。在侦探中做类似事情的类是here。
对于我的具体案例,我会:
Callable
中的wrapCallable
换行,例如,CallableWithAuthentication
类,在构建时将保留当前的身份验证CallableWithAuthentication
call
方法首先会恢复以前保存的Authentication
,然后调用原始操作,然后清理当前的Authentication
,等等。一旦HystrixConcurrencyStrategy
启动,您的请求拦截器将再次起作用,即使使用线程隔离也是如此。
注意检查项目的其余部分还有很多其他有趣的工具(例如RxJava)。
答案 1 :(得分:0)
只是为了详细说明@sebastian 的回答
public class RequestContextHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
@Override
public <T> Callable<T> wrapCallable(Callable<T> callable) {
return new RequestAttributeAwareCallable<>(callable, RequestContextHolder.getRequestAttributes());
}
static class RequestAttributeAwareCallable<T> implements Callable<T> {
private final Callable<T> delegate;
private final RequestAttributes requestAttributes;
public RequestAttributeAwareCallable(Callable<T> callable, RequestAttributes requestAttributes) {
this.delegate = callable;
this.requestAttributes = requestAttributes;
}
@Override
public T call() throws Exception {
try {
RequestContextHolder.setRequestAttributes(requestAttributes);
return delegate.call();
} finally {
RequestContextHolder.resetRequestAttributes();
}
}
}
}
然后在配置中的某个地方
@PostConstruct
public void init() {
HystrixPlugins.getInstance().registerConcurrencyStrategy(new RequestContextHystrixConcurrencyStrategy());
}