在将 Jetty 从 8.x 升级到 9.x 之后,ContinuationListener 似乎无法在由 Jetty 的 ProxyServlet 终止的过滤器链中工作
ContinuationListener does not seem to work in a filter chain terminated by Jetty's ProxyServlet, after upgrading Jetty from 8.x to 9.x
环境:
- 在我的环境中,Kibana 4.5.2 运行 位于 "reverse proxy servlet" 之后,它是通过扩展 Jetty 的 "ProxyServlet" class.
创建的
- 这样做是为了可以使用 URL https://Jetty_Server_IP:8443/visual-analytics/proxy/... Requests for this URL are intercepted by the reverse proxy running in the Jetty Server and redirected to https://localhost:5601/... 访问 Kibana Web 界面,即与 运行 在同一台机器上的 Kibana 服务器Jetty 服务器。
- Kibana 服务器随后处理由 Jetty 服务器转发的请求,并returns将响应返回给 Web 浏览器。
- 注意: Jetty 在我的应用程序中 "embedded mode" 运行。
问题:
"reverse proxy servlet"映射到URL“/visual-analytics/proxy/*”。
还有另一个 "filter" 映射到 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() 方法。
任何关于可能出错的地方或如何进一步调试此问题的指示将不胜感激。期待任何回应...
仅供参考,我按如下方式解决了这个问题:
- 将之前使用 Jetty "ContinuationListener" 的方法替换为 Servlet 3.0 的 "AsyncListener",因为升级到 Jetty 9.3 后 Jetty 的 "ContinuationListener" 似乎不起作用.14.v20161028。这可能是 Jetty 错误。
- 侦听器相关代码段位于过滤器的“chain.doFilter()”调用之前。我将此代码段移至过滤器的 "chain.doFilter()" 调用之后的位置,以便我可以在 Jetty ProxyServlet 的 service() 方法中检索 "already created" 的 AsyncContext。然后我可以将 AsyncListener 添加到检索到的 AsyncContext。
- 我没有在过滤器中使用“request.startAsync()”调用,而是使用“request.getAsyncContext()”,这样我就不会启动导致 IllegalStateException 的新 AsyncContext ,但只检索已在 Jetty 的 ProxyServlet 中创建的 AsyncContext。
因此更新后的代码段如下所示:
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);
环境:
- 在我的环境中,Kibana 4.5.2 运行 位于 "reverse proxy servlet" 之后,它是通过扩展 Jetty 的 "ProxyServlet" class. 创建的
- 这样做是为了可以使用 URL https://Jetty_Server_IP:8443/visual-analytics/proxy/... Requests for this URL are intercepted by the reverse proxy running in the Jetty Server and redirected to https://localhost:5601/... 访问 Kibana Web 界面,即与 运行 在同一台机器上的 Kibana 服务器Jetty 服务器。
- Kibana 服务器随后处理由 Jetty 服务器转发的请求,并returns将响应返回给 Web 浏览器。
- 注意: Jetty 在我的应用程序中 "embedded mode" 运行。
问题:
"reverse proxy servlet"映射到URL“/visual-analytics/proxy/*”。
还有另一个 "filter" 映射到 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() 方法。
任何关于可能出错的地方或如何进一步调试此问题的指示将不胜感激。期待任何回应...
仅供参考,我按如下方式解决了这个问题:
- 将之前使用 Jetty "ContinuationListener" 的方法替换为 Servlet 3.0 的 "AsyncListener",因为升级到 Jetty 9.3 后 Jetty 的 "ContinuationListener" 似乎不起作用.14.v20161028。这可能是 Jetty 错误。
- 侦听器相关代码段位于过滤器的“chain.doFilter()”调用之前。我将此代码段移至过滤器的 "chain.doFilter()" 调用之后的位置,以便我可以在 Jetty ProxyServlet 的 service() 方法中检索 "already created" 的 AsyncContext。然后我可以将 AsyncListener 添加到检索到的 AsyncContext。
- 我没有在过滤器中使用“request.startAsync()”调用,而是使用“request.getAsyncContext()”,这样我就不会启动导致 IllegalStateException 的新 AsyncContext ,但只检索已在 Jetty 的 ProxyServlet 中创建的 AsyncContext。
因此更新后的代码段如下所示:
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);