在Jersey 2中使用Hystrix Java Servlet和Servlet过滤器

3

我正在使用 Netflix 的 Hystrix 库来构建一个 REST 客户端并进行断路器设置以连接远程服务。我想通过他们提供的库来设置事件流和仪表盘监控。查看他们的示例应用程序here,似乎需要将他们的 Servlet 过滤器和 Servlet 类应用到我的 Web 应用程序中。

我使用 Spring Boot 和 Jersey 2,在 JerseyConfig.java 中连接我的资源和过滤器(没有 web.xml)。我知道 Jersey 过滤器与 Servlet 过滤器不同,并且很难将两者整合在一起。

那么,如何将 Java Servlet 过滤器转换为 Jersey 过滤器,并将 Java Servlet 转换为 Jersey 资源?

对于 Servlet,我当前的策略是将其封装如下,每个一个。

@Path("/hystrix.stream")
public class HystrixResource extends HystrixUtilizationSseServlet {

    @Context
    HttpServletRequest httpRequest;

    @Context
    HttpServletResponse httpResponse;

    //This returns void because it is a text/stream output that must remain open, 
    //so the httpResponse is continually written to until the conenction is closed
    @GET
    public void doGet() throws ServletException, IOException {
        doGet(httpRequest, httpResponse);
    }
}

这可能有效,但由于某些原因数据基本上为空。我猜测原因是因为过滤器没有起作用。
data: {"type":"HystrixUtilization","commands":{},"threadpools":{}}

我不太清楚如何包装Servlet Filters,因为它们期望的输入和输出与Jersey ContainerRequestFilter不同。在我的JerseyConfig中实现以下内容似乎没有任何作用,因为日志没有表明过滤器已被注册,并且我无法在调试模式下断点这些文件中的行。

@Component
@ApplicationPath("/")
public class JerseyConfig extends ResourceConfig {
    private static final Logger LOGGER = Logger.getLogger("JerseyConfig");
    public JerseyConfig(){
        //filter to provide a bridge between JAX-RS and Spring request attributes
        register(RequestContextFilter.class);
        register(SpringComponentProvider.class);
        //handles custom serialization
        register(new ObjectMapperContextResolver());
        //try to register the filters - which doesn't work because these aren't Jersey Filters
        register(HystrixRequestContextServletFilter.class);
        register(HystrixRequestLogViaResponseHeaderServletFilter.class);
        registerResources();

        /*
         * Enable the logging filter to see the HTTP response for each request.
         */
        register(new LoggingFilter(LOGGER, true));
    }
}
2个回答

1
Servlet和Servlet过滤器不应在Jersey配置中注册,否则它们将被忽略。您应该使用ServletRegistrationBeanFilterRegistrationBean在Spring Boot中注册它们。
在Spring配置中,您可以这样做:
@Bean
public ServletRegistrationBean someServlet() {
    ServletRegistrationBean registration = ServletRegisrationBean(
            new HystrixMetricsStreamServlet(), "/hystrix.stream");
    registration.setName("HystrixMetricsStreamServlet");
    return registration;
}

@Bean
public FilterRegistrationBean someFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new HystrixRequestContextServletFilter());
    registration.setUrlPatterns(Arrays.asList("/*"));
    registration.setName("HystrixRequestContextServletFilter");
    // you can also set the order of filters if you need to 
    return registration;
}

另外:

  • 你不需要注册SpringComponentProvider,它会自动注册。
  • 如果你试图访问通过这种方式注册的Servlet时出现404错误,则可能是因为你正在使用默认的Jersey映射/*,它占用了所有请求。你可以更改映射或将Jersey注册为过滤器来转发未找到的请求。请参见此帖子

嗨@peeskillet。感谢您的回复。我没有通过Spring Web提供页面,所以您的任何回复都适用吗? - th3morg
提供页面与问题有什么关系?您已经标记了Spring Boot,因此我为您提供Spring Boot解决方案。我不知道提供页面在这个问题中的任何作用。 - Paul Samsotha
谢谢@peeskillet。我能够根据您的建议使其工作。值得注意的是,hystrix.stream的servlet应该是HystrixMetricsStreamServlet,而不是HystrixUtilizationSseServlet。我会尝试进行编辑。其次,在执行命令之前不会有任何数据存在。因此,如果您重新启动应用程序,则数据将为空,直到请求通过您的HystrixCommands。谢谢! - th3morg

0

另一种选择,也是我最终采用的方法,是在Spring Boot项目中使用Spring Cloud/Boot Starters。这样可以避免像其他答案中所示那样需要显式定义bean和filter。最终基本上可以直接使用。

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-hystrix</artifactId>
        <exclusions>
            <!--We're running our Jersey server w/ Jackson 2. This import uses Jackson 1.x and creates a breaking conflict.-->
            <exclusion>
                <groupId>javax.ws.rs</groupId>
                <artifactId>jsr311-api</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

参考断路器入门指南。我遇到的唯一问题是Jackson 1与Jackson 2的冲突,但我能够添加库排除。基本上,我之前有Hystrix库jar包,但没有任何连接使其工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接