Tôi gặp sự cố tài nguyên trong ứng dụng máy chủ netty của mình.Máy chủ Netty không đóng/giải phóng ổ cắm
[io.netty.channel.DefaultChannelPipeline] An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.: java.io.IOException: Too many open files
at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method) [rt.jar:1.7.0_60]
at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:241) [rt.jar:1.7.0_60]
at io.netty.channel.socket.nio.NioServerSocketChannel.doReadMessages(NioServerSocketChannel.java:135) [netty-all-4.0.25.Final.jar:4.0.25.Final]
at io.netty.channel.nio.AbstractNioMessageChannel$NioMessageUnsafe.read(AbstractNioMessageChannel.java:69) [netty-all-4.0.25.Final.jar:4.0.25.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511) [netty-all-4.0.25.Final.jar:4.0.25.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468) [netty-all-4.0.25.Final.jar:4.0.25.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382) [netty-all-4.0.25.Final.jar:4.0.25.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354) [netty-all-4.0.25.Final.jar:4.0.25.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116) [netty-all-4.0.25.Final.jar:4.0.25.Final]
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137) [netty-all-4.0.25.Final.jar:4.0.25.Final]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_60]
Là một workaround tôi tăng các tập tin mở tối đa với ulimit -n, nhưng tôi vẫn có thể whatch số lượng file/ổ cắm tăng:
lsof -p 5604 | grep socket | wc -l
bây giờ cũng hơn 3000 ...
Không thể thấy bất kỳ kết nối mở hoặc treo nào với netstat ...
Tôi sử dụng ReadTimeoutHandler để đóng các kết nối không được sử dụng với mã ngoại lệHandler:
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (cause instanceof ReadTimeoutException) {
logger.debug("Read timeout - close connection");
} else {
logger.info(cause.getMessage());
}
ctx.close();
}
server bootstrap trông như thế này:
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ReadTimeoutHandler(60));
ch.pipeline().addLast(new LoggingHandler(mySpec.getPortLookupKey().toLowerCase()));
ch.pipeline().addLast(new RawMessageEncoder());
ch.pipeline().addLast(new RawMessageDecoder());
ch.pipeline().addLast(new RequestServerHandler(ctx.getWorkManager(), factory));
}
}).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture channelFuture = b.bind(port).sync();
đã làm tôi nhớ một cái gì đó? Không nên số lượng tệp mở giảm sau khi kết nối được đóng (hoặc bởi máy chủ từ xa hoặc bởi trình xử lý thời gian chờ)?
Tôi cần thay đổi gì để lưu tài nguyên ở đây?
Cập nhật: Tôi sử dụng Netty 4.0.25
Cập nhật 2: Theo yêu cầu tôi chuyển xử lý khai thác gỗ ở phía trước của ReadTimeouthandler, sau đây là các bản ghi. Tình hình nơi khách hàng thường ngắt kết nối:
09:41:39,755 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 => /127.0.0.1:4300] REGISTERED
09:41:39,756 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 => /127.0.0.1:4300] ACTIVE
09:41:39,810 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 => /127.0.0.1:4300] RECEIVED(1024B)
09:41:39,813 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 => /127.0.0.1:4300] RECEIVED(1024B)
09:41:39,814 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 => /127.0.0.1:4300] RECEIVED(150B)
09:41:40,854 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 => /127.0.0.1:4300] WRITE(1385B)
09:41:40,855 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 => /127.0.0.1:4300] FLUSH
09:41:40,861 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 :> /127.0.0.1:4300] INACTIVE
09:41:40,864 [3-1] [id: 0xca6601a2, /127.0.0.1:64258 :> /127.0.0.1:4300] UNREGISTERED
Tình hình, nơi mà khách hàng không ngắt kết nối:
10:04:24,104 [3-1] [id: 0x48076684, /127.0.0.1:50525 => /127.0.0.1:4300] REGISTERED
10:04:24,107 [3-1] [id: 0x48076684, /127.0.0.1:50525 => /127.0.0.1:4300] ACTIVE
10:04:24,594 [3-1] [id: 0x48076684, /127.0.0.1:50525 => /127.0.0.1:4300] RECEIVED(1024B)
10:04:24,597 [3-1] [id: 0x48076684, /127.0.0.1:50525 => /127.0.0.1:4300] RECEIVED(1024B)
10:04:24,598 [3-1] [id: 0x48076684, /127.0.0.1:50525 => /127.0.0.1:4300] RECEIVED(150B)
10:04:25,638 [3-1] [id: 0x48076684, /127.0.0.1:50525 => /127.0.0.1:4300] WRITE(1383B)
10:04:25,639 [3-1] [id: 0x48076684, /127.0.0.1:50525 => /127.0.0.1:4300] FLUSH
10:05:25,389 [3-1] [id: 0x48076684, /127.0.0.1:50525 => /127.0.0.1:4300] CLOSE()
10:05:25,390 [3-1] [id: 0x48076684, /127.0.0.1:50525 :> /127.0.0.1:4300] CLOSE()
10:05:25,390 [3-1] [id: 0x48076684, /127.0.0.1:50525 :> /127.0.0.1:4300] INACTIVE
10:05:25,394 [3-1] [id: 0x48076684, /127.0.0.1:50525 :> /127.0.0.1:4300] UNREGISTERED
Vì vậy, có 60 lỗ hổng trước khi đóng cửa (như mong đợi từ ReadTimeoutHandler)
Sau một số phân tích nhiều hơn, tôi có ấn tượng, rằng ngay cả với một ngắt kết nối bình thường từ khách hàng, số lượng các tập tin mở tăng lên! Ngoài ra, không có CLOSE() trong tình huống đó ...
bạn đang sử dụng phiên bản Netty nào? – HCarrasko
Bạn có thể chèn một 'LoggingHandler' với mức nhật ký đủ cao trước' ReadTimeoutHandler' vào đường ống của bạn và cập nhật câu hỏi của bạn bằng nhật ký không? – trustin
Có lẽ, đó là một cái gì đó liên quan đến SO, những sự kiện kết nối dường như khá bình thường đối với tôi, và tôi chưa bao giờ thấy một vấn đề như vậy. Có một phiên bản mới 4.0.28, bạn có thể thử với nó không? – crigore