【发布时间】:2017-06-13 06:11:44
【问题描述】:
在注解为@HystrixCommand 的Javanica 中,我们通过检查来检查请求是否在实际的HTTP servlet 请求中:
RequestContextHolder.getRequestAttributes() != null;
但是从 @HystrixCommand 调用时,此条件始终为 false,即使请求来自 Spring MVC 请求。
如果我删除 @HystrixCommand 注释一切正常。
我们还尝试直接使用HttpServletRequest,这很好用(没有@HystrixCommand):
LOGGER.info(request.getHeader("X-Client"));
使用带注释的@HystrixCommand,我们面临异常,表明我不在有效的HttpServletRequest 中。我知道这是由于 Hystrix 在与其自己的 ThreadPool 不同的线程中运行命令并尝试这样做,但也不起作用:
public class RequestServletFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// No Impl
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HystrixRequestContext context = HystrixRequestContext.initializeContext();
try {
chain.doFilter(request, response);
} finally {
context.shutdown();
}
}
@Override
public void destroy() {
// No Impl
}
有人知道如何将 Spring HttpServletRequest 委托给 HystrixCommands 吗?
感谢任何帮助。
【问题讨论】:
-
嗯...实际上你访问请求是不是有点臭?感觉就像你在尝试做一些你一开始就不应该做的事情。
-
我们的应用程序服务于不同的国家(客户端),因此在构建 REST url 以从第三方后端检索数据时,必须在 URL 中考虑客户端。因此,我们将这个客户端处理委托给一个自定义的 ClientContext.java,我们可以在需要时自动装配它。这只是为了舒适,否则我们需要到处循环访问客户端,这很痛苦。
-
但是这与将
HttpServletRequest注入@HystrixCommand注释方法有什么关系?也很高兴知道您使用的是普通的 Hystrix 还是 Spring Cloud 包装的?我会说您的ClientContext应该与请求分离(您可能希望根据传入的请求创建它,但之后不应再依赖它)。这将使共享对象(我希望它是只读的)更容易。 -
我们使用的是普通的 hystrix + javanica 1.5.9。我们不直接在 @HystrixCommand 注释的存储库中自动装配 HttpServletRequest,而是在 ClientContext 中自动装配。 ClientContext 通过提供方法 getRequestSpecificClient(); 来使用 HttpServletRequest;如果没有可用的 HttpServletRequest,此方法返回 null。在这种情况下有,但由于分离的 HystrixCommand 线程,它仍然返回 null。解决方法是仅检查服务中的当前客户端,然后将客户端路由到任何地方。但正如我所说,这很不方便
-
这就是为什么我建议
ClientContext无论当前请求与否都应该工作。这可能依赖于RequestContextHolder,即ThreadLocal。恕我直言,您应该使用所需的属性填充ClientContext以完成其工作。如果您使用它来访问代码库中任何地方的当前请求,我会说这是一种气味。