在将Jetty从8.x升级到9.x后,ContinuationListener似乎无法在由Jetty的ProxyServlet终止的过滤器链中工作

时间:2017-02-21 18:13:04

标签: java reverse-proxy servlet-filters embedded-jetty jetty-9

环境:

  • 在我的环境中,Kibana 4.5.2运行在"反向代理servlet"这是通过扩展Jetty" ProxyServlet"类。
  • 这样做是为了可以使用URL https://Jetty_Server_IP:8443/visual-analytics/proxy/访问Kibana Web界面...此URL的请求被Jetty服务器中运行的反向代理拦截并重定向到https://localhost:5601/。 ..即,与Jetty Server在同一台机器上运行的Kibana服务器。
  • 然后,Kibana Server处理Jetty服务器转发的请求,并将响应返回给Web浏览器。
  • 注意: Jetty正在"嵌入模式"在我的申请中。

问题:

"反向代理servlet"被映射到URL" / visual-analytics / proxy / *"。

还有另一个"过滤器"映射到URL" /visual-analytics/proxy/elasticsearch/.kibana/search / *"其中正在使用“ContinuationListener”,如以下代码段所示:

    ContinuationSupport.getContinuation(myRequestWrapper).addContinuationListener(new ContinuationListener() {

                        @Override
                        public void onTimeout(Continuation continuation) {
                            logger.log(Level.WARNING, "Request timeout...");
                        }

                        @Override
                        public void onComplete(Continuation continuation) {

                            HttpServletResponse httpResponse = (HttpServletResponse)continuation.getServletResponse();
                            if (httpResponse.getStatus() == HttpServletResponse.SC_OK || httpResponse.getStatus() == HttpServletResponse.SC_CREATED ) {                                                                       
                                    //some business logic
                            }

                        }
                    });

    chain.doFilter(myRequestWrapper, response);

上面的ContinuationListener与 Jetty版本8.1.15.v20140411 一起正常工作,并且正在调用侦听器的onComplete()方法。但是在将Jetty版本升级到 9.3.14.v20161028 之后,ContinuationListener不再工作,即,不会调用侦听器的onComplete()方法和onTimeout()方法。

任何可能出错的指针或如何进一步调试此问题将不胜感激。期待任何回应...

1 个答案:

答案 0 :(得分:0)

仅供参考我修正了这个问题如下:

  1. 取代了之前使用Jetty" ContinuationListener"使用Servlet 3.0" AsyncListener",因为Jetty" ContinuationListener"升级到 Jetty 9.3.14.v20161028 后似乎无法正常工作。这可能是一个Jetty bug。
  2. 侦听器相关代码段位于过滤器的“chain.doFilter()”调用之前。我将此代码段移动到过滤器" chain.doFilter()"之后的位置。调用,以便我可以检索已经创建的AsyncContext"在Jetty ProxyServlet的service()方法中。然后,我可以向检索到的AsyncContext添加AsyncListener。
  3. 我没有在我的过滤器中使用“request.startAsync()”调用,而是使用“request.getAsyncContext()”,这样我就不会启动一个新的AsyncContext导致IllegalStateException,而只是检索AsyncContext已经在Jetty的ProxyServlet中创建了。
  4. 因此更新的代码段如下所示:

            chain.doFilter(myRequestWrapper, response);
    
            AsyncContext asyncContext = myRequestWrapper.getAsyncContext();
            asyncContext.addListener(new AsyncListener() {
    
                @Override
                public void onTimeout(AsyncEvent event) throws IOException 
                {
                            logger.log(Level.WARNING, "Async timeout...");
                }
    
                @Override
                public void onStartAsync(AsyncEvent event) throws IOException 
                {
                            logger.log(Level.INFO, "Async start...");
                }
    
                @Override
                public void onError(AsyncEvent event) throws IOException 
                {
                            logger.log(Level.SEVERE, "Async error...");
                }
    
                @Override
                public void onComplete(AsyncEvent event) throws IOException 
                {
                        HttpServletResponse httpResponse = (HttpServletResponse) event.getAsyncContext().getResponse();
                        if (httpResponse.getStatus() == HttpServletResponse.SC_OK || httpResponse.getStatus() == HttpServletResponse.SC_CREATED ) {
                                    //some business logic
                        }
                }
            }, myRequestWrapper, httpServletResponse);