【发布时间】:2015-10-28 00:01:07
【问题描述】:
我遇到了以下情况:我正在尝试在 java 中实现一个长轮询 servlet(将在码头上运行)。我正在使用 AsyncContext 和 TimerTask 来实现这一点。
我有一个具有这种方法的会话类:
public boolean setLongPollingContext(final AsyncContext ctx) {
if (ctx==null)
return false;
this.longPollContext = ctx;
this.alertHandler = new AlertNotificationHandler() {
@Override
public void onNewAlert() {
}
@Override
public void onTimeout() {
System.out.println("*** timeout ***");
HttpServletResponse response = (HttpServletResponse)ctx.getResponse();
response.setStatus(408); // timeout
try {
response.getWriter().write("Timeout");
} catch (IOException e) {
e.printStackTrace();
}
ctx.complete();
}
};
this.alertHandler.setTimeout(this.longPollingInterval); // 31 seconds
return true;
}
(setTimeout 只是启动一个计时器线程,它在 31 秒内调用“onTimeout”)
我这样称呼它:
final AsyncContext asyncCtx = request.startAsync(request, response);
session.setLongPollingContext(asyncCtx);
它在 30 秒内运行良好(这显然是 jetty 9.3 中默认的 ssl/http 线程超时)。
超过 30 秒,我遇到了与超时相关的问题,我通过在 appease/start.d/ssl.ini 文件中设置这一行来解决这个问题:
## Connector idle timeout in milliseconds
jetty.ssl.idleTimeout=330000
我不再遇到超时问题了,但现在我遇到了更奇怪的问题:
Exception in thread "Timer-0"
java.lang.IllegalStateException: Locker is not reentrant
at org.eclipse.jetty.util.thread.Locker.concLock(Locker.java:85)
at org.eclipse.jetty.util.thread.Locker.lock(Locker.java:61)
at org.eclipse.jetty.server.HttpChannelState.getStatusString(HttpChannelState.java:166)
at org.eclipse.jetty.server.HttpChannelState.complete(HttpChannelState.java:481)
at org.eclipse.jetty.server.AsyncContextState.complete(AsyncContextState.java:92)
at com.theobroma.paranoidandroid.session.ProxyClientSession$1.onTimeout(ProxyClientSession.java:60)
at com.theobroma.paranoidandroid.session.AlertNotificationHandler$1.run(AlertNotificationHandler.java:25)
at java.util.TimerThread.mainLoop(Unknown Source)
at java.util.TimerThread.run(Unknown Source)
Google 未能向我提供任何与此相关的向量。
还有什么我需要在码头配置的吗?
有没有办法在不更改配置文件的情况下设置这些配置选项(从代码中,例如使用注释或设置一些静态变量?)
谢谢!
【问题讨论】:
-
为什么要自己实现超时,而不是使用 AsyncContext 中的内置超时?
-
嗯,主要是因为我希望能够在超时时做一些事情。我不知道内置程序是否可以做到这一点,但这非常有帮助,因为显然内置计时器是过期并使我的响应输出流无效的计时器。所以将超时设置为 longPollingInterval+something 解决了这个问题,谢谢!
-
如果你想把它变成一个答案,这样我可以接受它,其他人可以更容易地看到它:)
标签: java servlets jetty long-polling