繁体   English   中英

异步Java Jetty Servlet长轮询中的“锁定器不可重入”

[英]“Locker is not reentrant” in asynchronous java jetty servlet long polling

我遇到以下情况:我正在尝试在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秒内正常工作(显然,这是码头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在此方面没有给我提供任何相关的指导。

我还需要在码头配置一些其他东西吗?

有没有一种方法可以在不更改配置文件的情况下设置这些配置选项(通过代码,例如带有批注或设置一些静态变量的代码)?

谢谢!

Joakim Erdfelt给了我一些非常有用的提示,我将在答复中进行汇总,因为它可以为我解决问题。

因此,似乎问题在于AsyncContext有其自己的超时,该超时默认设置为我的30秒(我猜想它与30秒的跳船无关,这只是一个误导性的巧合)

一旦异步上下文超时,请求和响应流将关闭并且无法再次打开,因此会出现错误。

解决方案是增加异步上下文的超时时间:

ctx.setTimeout(this.longPollingInterval+1000);

我为此添加了一些额外的时间,以确保它不会在我自己的超时线程之前超时。

有一种方法可以将超时事件的侦听器分配给异步上下文。 我将对此进行研究,并使用它代替我自己的超时线程。 我对Java很陌生,所以我对此一无所知:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM