【问题标题】:Spring HttpServletRequest unaccessible in HystrixCommand在 HystrixCommand 中无法访问 Spring HttpServletRequest
【发布时间】: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 以完成其工作。如果您使用它来访问代码库中任何地方的当前请求,我会说这是一种气味。

标签: spring hystrix


【解决方案1】:

默认情况下使用RequestContextHolder 时,它的参数不共享(有充分的理由!)。

假设您使用DispatcherServlet 来处理您的请求,您可以将其[threadContextInheritable] 设置为true,以便在请求之间共享RequestContextLocaleContext

RequestContextFilter 也是如此,RequestContextListener 则不可能。

注意:我会考虑在线程之间共享HttpServletRequest,这是您不应该做的事情,应该非常小心!

【讨论】:

  • 我假设当您开始在 Hystrix 中使用 RequestCollapsing 时,将 HttpServletRequest 共享给 HystrixCommand 会变得一团糟。
猜你喜欢
  • 2012-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-15
  • 1970-01-01
  • 2017-04-27
  • 2022-01-27
  • 2012-04-03
相关资源
最近更新 更多