是否可以将大文件上传到 Ktor & Netty 服务器?

Nik*_*kel 6 netty kotlin ktor

我正在制作一个简单的文件上传和下载服务,并发现,据我了解,Netty 在请求处理结束之前不会释放直接缓冲区。因此,我无法上传更大的文件。

我试图确保问题不在我的代码内部,因此我创建了最简单的小型 Ktor 应用程序:

routing {
    post("upload") {
        call.receiveMultipart().forEachPart {}
        call.respond(HttpStatusCode.OK)
    }
}
Run Code Online (Sandbox Code Playgroud)

默认直接内存大小约为 3Gb,为了使测试更简单,我将其限制为:

System.setProperty("io.netty.maxDirectMemory", (10 * 1024 * 1024).toString())
Run Code Online (Sandbox Code Playgroud)

在启动 NettyApplicationEngine 之前。

现在,如果我上传一个大文件,例如使用 httpie,我会得到“连接重置”:

http -v --form POST http://localhost:42195/upload file@/tmp/FileStorageLoadTest-test-data1.tmp

http: error: ConnectionError: ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer')) while doing POST request to URL: http://localhost:42195/upload
Run Code Online (Sandbox Code Playgroud)

在服务器端,除了“java.io.IOException:发生损坏的分隔符”异常之外,没有有关该问题的信息。但如果我将断点放在 NettyResponsePipeline#processCallFailed 中,真正的异常是:

io.netty.util.internal.OutOfDirectMemoryError: failed to allocate 65536 byte(s) of direct memory (used: 10420231, max: 10485760)
Run Code Online (Sandbox Code Playgroud)

遗憾的是这个异常没有被记录下来。

另外,我发现如果我使用 Jetty 引擎,相同的代码可以正常工作。

环境:

Ubuntu Linux
Java 8
Ktor=1.2.5
netty-transport-native-epoll=4.1.43.Final 
Run Code Online (Sandbox Code Playgroud)

(但是如果Netty启动时没有native-epoll支持,问题是一样的)