简单的Java Thrift服务器引发了Out of Memory异常

时间:2017-12-04 12:48:03

标签: 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

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

SimpleHandler.java

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();
    }
}

然后我通过启动1000个并发线程测试此服务器,每个线程发送一个具有1秒睡眠时间和4 MB二进制数据的请求。

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)

我读了Thrift源代码,并且知道最大的内存消耗是读缓冲区的分配。我将serverArgs.maxReadBufferBytes设置为256 MB以防止内存不足。但它仍然会抛出Out of Memory Exception。我确信通过读取源代码并打印一些运行信息来正确限制分配的读缓冲区。

我无法弄清楚为什么它仍会引发Out of Memory异常。

1 个答案:

答案 0 :(得分:0)

您需要在客户端使用TFramedTransport。此传输由您选择的服务器隐式应用,或者换句话说:服务器希望客户端使用它。