簡體   English   中英

Jetty WebSocket服務器不會釋放二進制消息字節緩沖池

[英]Jetty WebSocket server won't release binary message byte buffer pool

我正在使用Jetty的JSR356 WebSocket實現編寫一個簡單的嵌入式WebSocket服務器。 我的服務器偵聽本地端口,Web應用程序將創建從瀏覽器到本地服務器的WebSocket連接,並將二進制數據發送到服務器。 這是我的服務器代碼示例:

服務器:

public class WSServer {

    public static void main(String[] args) {
        Server server = new Server();

        // Connector
        ServerConnector connector = new ServerConnector(server);
        connector.setPort(8080);

        ServletContextHandler ctx = new ServletContextHandler(ServletContextHandler.SESSIONS);
        ctx.setContextPath("/");

        server.setHandler(ctx);
        server.addConnector(connector);

        try {
            // Initialize javax.websocket layer
            ServerContainer wscontainer = WebSocketServerContainerInitializer.configureContext(ctx);

            // Add WebSocket endpoint to javax.websocket layer
            wscontainer.addEndpoint(WSEndpoint.class);
            wscontainer.setDefaultMaxSessionIdleTimeout(0);
            wscontainer.setDefaultMaxTextMessageBufferSize(Integer.MAX_VALUE);
            wscontainer.setDefaultMaxBinaryMessageBufferSize(Integer.MAX_VALUE);

            server.start();
            server.join();
        } catch (Throwable t) {
            t.printStackTrace(System.err);
        }
    }
}

服務器端點:

@ServerEndpoint("/")
public class WSEndpoint {

    @OnOpen
    public void onOpen(Session session) throws IOException {
        session.getBasicRemote().sendText("onOpen");
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("Received text message: " + message);
    }

    @OnMessage
    public void onBinary(ByteBuffer bb, Session session) {
        System.out.println("Got binary message, do nothing to make sure there is no reference to ByteBuffer and Session");
    }

    @OnError
    public void onError(Throwable t) {
        t.printStackTrace();
    }

    @OnClose
    public void onClose(Session session) {

    }
}

在此示例中,對傳入的二進制字節緩沖區不執行任何操作,以避免出於測試目的對該對象的任何引用。

但是,在進行了一些傳輸了多個文件的測試后,該服務器的內存使用量顯着增長,並且幾乎沒有下降。 即使斷開連接,內存仍然不會關閉,在不得不停止服務器之前,它會占用1.5 GB的內存。

然后,我轉儲了內存,發現所有已傳輸的二進制文件都由org.eclipse.jetty.io.MappedByteBufferPool對象保存在內存中,並且從未釋放過。 IMO,Jetty將照顧這個MappedByteBufferPool並在適當的時候釋放內存,因為它沒有暴露給我們,但似乎緩沖池從未被釋放。

所以我的問題是:

  1. 我的代碼有做錯什么嗎?
  2. 如果代碼正確,如何解決此問題?

謝謝!

這是Jetty 9.3.4.v20151007修復的錯誤,並在9.3.5.v20151012進一步完善。

相關錯誤:

  • 錯誤#478829 :WebsocketSession無法清理/內存泄漏
  • 錯誤#474936 :並非總是從openSessions中清除WebSocketSessions

我想發布我從Jetty錯誤報告中獲得的解決方案,感謝@Joakim Erdfelt的重放,對於可能遇到相同問題的任何人:

對於大文件傳輸,請使用流而不是ByteBuffer:

@OnMessage
public void onBinary(InputStream in, Session session) {
    System.out.println("Got binary message");
}

但請注意,作為我的測試,此解決方案適用於IE和Chrome,但如果從Firefox瀏覽器傳輸文件,它仍會累積MappedByteBuffer對象的內存使用量,至少要針對當前最新的Jetty版本9.3.6。

暫無
暫無

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

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