簡體   English   中英

如何處理ServerSocketChannel.accept()IOException:NIO中打開的文件太多了?

[英]How do I handle ServerSocketChannel.accept() IOException: too many open files in NIO?

我的服務器有問題,星期五早上我收到了以下IOException:

11/Sep/2015 01:51:39,524 [ERROR] [Thread-1] - ServerRunnable: IOException: 
java.io.IOException: Too many open files
    at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method) ~[?:1.7.0_75]
    at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:241) ~[?:1.7.0_75]
    at com.watersprint.deviceapi.server.ServerRunnable.acceptConnection(ServerRunnable.java:162) [rsrc:./:?]
    at com.watersprint.deviceapi.server.ServerRunnable.run(ServerRunnable.java:121) [rsrc:./:?]
    at java.lang.Thread.run(Thread.java:745) [?:1.7.0_75]

ServerRunnable類的第162行在下面的方法中,它是ssc.accept()調用。

private void acceptConnection(Selector selector, SelectionKey key) {

    try {
        ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
        SocketChannel sc = ssc.accept();
        socketConnectionCount++;

        /*
         * Test to force device error, for debugging purposes
         */
        if (brokenSocket
                && (socketConnectionCount % brokenSocketNumber == 0)) {

            sc.close();

        } else {

            sc.configureBlocking(false);
            log.debug("*************************************************");
            log.debug("Selector Thread: Client accepted from "
                    + sc.getRemoteAddress());

            SelectionKey newKey = sc.register(selector,
                    SelectionKey.OP_READ);
            ClientStateMachine clientState = new ClientStateMachine();
            clientState.setIpAddress(sc.getRemoteAddress().toString());
            clientState.attachSelector(selector);
            clientState.attachSocketChannel(sc);
            newKey.attach(clientState);

        }

    } catch (ClosedChannelException e) {

        log.error("ClosedChannelException: ", e);
        ClientStateMachine clientState = (ClientStateMachine)key.attachment();
        database.insertFailedCommunication(clientState.getDeviceId(),
                clientState.getIpAddress(),
                clientState.getReceivedString(), e.toString());
        key.cancel();

    } catch (IOException e) {
        log.error("IOException: ", e);

    }

}

我該怎么處理? 閱讀錯誤,它似乎是Linux操作系統中的一個設置,它限制了進程可以擁有的打開文件的數量。 從這一點來看, 這個問題 ,似乎我沒有正確關閉套接字(服務器目前服務大約50個客戶端)。 這是一種情況,我需要一個計時器來監視打開的套接字並在一段時間后將它們計時?

在某些情況下,客戶端可以連接,然后在建立連接后不發送任何數據。 我以為我已經妥善處理了這些案件。

我的理解是,非阻塞的NIO服務器有很長的超時時間,如果我錯過了這樣的情況,它們可能會累積並導致此錯誤嗎?

此服務器已運行三個月,沒有任何問題。 在我查看代碼並檢查處理不當/丟失的情況后,處理此特定錯誤的最佳方法是什么? 我還應該考慮其他可能有助於此的事情嗎?

此外,(也許這應該是另一個問題)我有log4j2配置為發送電子郵件的日志級別的錯誤和更高,但我沒有收到此錯誤的電子郵件。 有什么理由可以嗎? 它通常工作,錯誤被記錄到日志文件中,但我從未收到有關它的電子郵件。 每次建立連接時都會發生錯誤,我應該已經充足了。

您修復了套接字泄漏。 當您在套接字上獲得EOS或除SocketTimeoutException,之外的任何IOException SocketTimeoutException,您必須將其關閉。 SocketChannels,的情況下SocketChannels,這意味着關閉頻道。 僅僅取消關鍵,或忽略問題並希望它會消失,是不夠的。 連接已經消失了。

您發現有必要計算損壞的套接字連接並捕獲ClosedChannelException,已經表明您的應用程序中存在嚴重的邏輯問題。 你不應該需要這個。 取消封閉渠道的密鑰並不能提供任何解決方案。

我的理解是,非阻塞的NIO服務器有很長的超時時間

非阻塞NIO服務器唯一超時是指定select()的超時。 內置於TCP堆棧的所有超時不受您使用NIO還是非阻塞模式的影響。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM