2015-11-11 4 views
1

Я пишу простой встроенный сервер WebSocket, используя реализацию JS356 WebSocket Jetty. Мой сервер прослушивает локальный порт, и веб-приложение создаст соединение WebSocket из браузера на локальный сервер и отправит двоичные данные на сервер. Вот мой код сервера Пример:Сервер Jetty 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); 
     } 
    } 
} 

Сервер Endpoint:

@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) { 

    } 
} 

В этом примере, не делать ничего для входящего бинарного ByteBuffer, чтобы избежать какой-либо ссылку на этот объект для целей тестирования.

Но после некоторого тестового запуска с несколькими переданными файлами использование памяти этого сервера значительно возрастает и вряд ли спускается. Даже отключить соединение, память все еще не работает, прежде чем мне пришлось остановить мой сервер, он занимает до 1,5 ГБ памяти.

Затем я сбрасывал память и выяснял, что все бинарные файлы, которые я передал, были сохранены в памяти объектом org.eclipse.jetty.io.MappedByteBufferPool и никогда не выпускались. IMO, Jetty позаботится об этом MappedByteBufferPool и выпустят память в надлежащее время, так как она не отображается нам, но кажется, что буферный пул никогда не выпускался.

Так что мои вопросы:

  1. ли я сделать что-нибудь неправильно в моем коде?
  2. Если код в порядке, как решить эту проблему?

Спасибо!

ответ

0

Это ошибка, исправленная в Jetty 9.3.4.v20151007 и дополнительно уточняется в 9.3.5.v20151012.

Соответствующие ошибки:

  • Bug #478829: WebsocketSession не очищены/утечку памяти
  • Bug #474936: WebSocketSessions не всегда очищены от openSessions
+0

Спасибо, но эти две ошибки, по-видимому, противоречат собственной реализации WebSocket Jetty, а не реализации jsr 356, похоже, что моя проблема также является ошибкой, возможно, я тоже должен зарегистрировать ошибку. –

+0

Реализация JSR356 - это слой над встроенной реализацией websocket. –

+0

У последней версии 9.3.5.v20151012 все еще есть одна и та же проблема. –

1

Я хотел бы, чтобы отправить решение, которое я получил от отчета об ошибке 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.

Смежные вопросы