2017-12-04 13 views
1

Java를 사용하여 매우 간단한 Thrift 서버를 구현했습니다.간단한 Java Thrift 서버가 메모리 부족 예외를 발생시킵니다.

이 서비스 SimpleServer.java

public class SimpleServer { 

    public static SimpleHandler handler; 
    public static SimpleService.Processor processor; 

    public static void main(String [] args) { 
     try { 
      handler = new SimpleHandler(); 
      processor = new SimpleService.Processor(handler); 
      InetAddress listenAddress = InetAddress.getByName("localhost"); 
      TNonblockingServerTransport serverTransport = new TNonblockingServerSocket(
        new InetSocketAddress(listenAddress, 9091)); 
      TTransportFactory transportFactory = new TFramedTransport.Factory(
        8 * 1024 * 1024); 
      THsHaServer.Args serverArgs = new THsHaServer.Args(serverTransport) 
        .processor(processor) 
        .transportFactory(transportFactory); 
      serverArgs.maxReadBufferBytes = (long) (256 * 1024 * 1024); 
      TServer server = new THsHaServer(serverArgs); 

      System.out.println("Starting server..."); 
      server.serve(); 
     } catch (Exception x) { 
      x.printStackTrace(); 
     } 
    } 

} 

만, 바이너리 데이터를 받아 지정된 초 동안 휴면 데이터 길이를 반환하는 기능이있다. IDL 및 핸들러 구현에 대해서는 아래를 참조하십시오. 목적은 데이터베이스 배치 쓰기와 같은 큰 입력을 허용하는 느린 작업을 에뮬레이션하는 것입니다.

simple.thrift

public class SimpleHandler implements SimpleService.Iface{ 
    @Override 
    public int hold(int seconds, ByteBuffer data) throws TException { 
     try { 
      Thread.sleep(seconds * 1000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     return data.capacity(); 
    } 
} 

namespace java generated 
service SimpleService { 
    i32 hold(1:i32 seconds, 2:binary data); 
} 

SimpleHandler.java 그러면 I는 각각 1 초 대기 시간과 4메가바이트 이진 데이터 요청을 전송 1,000 동시 스레드를 시작하여이 서버를 테스트한다.

ByteBuffer buffer = ByteBuffer.allocate(4 * 1024 * 1024); 
int result = client.hold(1, buffer); 

초의 테스트 프로세스 수십를 실행 한 후, 서버는 내가 드리프트 소스 코드를 읽고, 가장 큰 메모리 소비가 읽기 버퍼의 할당 알고

java.lang.OutOfMemoryError: Java heap space 
    at java.nio.HeapByteBuffer.<init>(HeapByteBuffer.java:57) 
    at java.nio.ByteBuffer.allocate(ByteBuffer.java:335) 
    at AbstractNonblockingServer$FrameBuffer.read(AbstractNonblockingServer.java:352) 
    at AbstractNonblockingServer$AbstractSelectThread.handleRead(AbstractNonblockingServer.java:184) 
    at TNonblockingServer$SelectAcceptThread.select(TNonblockingServer.java:182) 
    at TNonblockingServer$SelectAcceptThread.run(TNonblockingServer.java:133) 

가 발생합니다. 메모리 부족을 방지하기 위해 serverArgs.maxReadBufferBytes을 256MB로 설정했습니다. 하지만 여전히 Out of Memory 예외가 발생합니다. 나는 할당 된 읽기 버퍼가 정확하게 소스 코드를 읽고 일부 실행 정보를 인쇄함으로써 제한된다는 것을 확신합니다.

여전히 Out of Memory 예외가 발생하는 이유를 알 수 없습니다.

+1

각 스레드가 4MB 인 1000 개의 스레드는 얼마입니까? ''Xms''와''Xmx''vm 매개 변수에 어떤 값을 사용합니까? – f1sh

+0

hw에서 사용 가능한 메모리는 얼마입니까? – Erik

+0

@ f1sh 각각 4MB입니다. 나는'Xms'와'Xmx'를 설정하지 않습니다. 기본 설정이어야합니다. 메모리 사용량을보기 위해'jvisualvm'을 사용합니다. 최대 힙 크기는 약 2G입니다. – gzc

답변

0

클라이언트 측에서 TFramedTransport을 사용해야합니다. 이 전송은 사용자가 선택하는 서버에 의해 암시 적으로 적용됩니다. 즉, 서버는 클라이언트가 클라이언트를 사용할 것으로 기대합니다.

+0

이미 테스트 프로그램에서'TFramedTransport'를 사용하고 있습니다. 이 일과 관련이 없어야합니다. – gzc