簡體   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