2015-03-02 14 views
8

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 đó ...

+0

bạn đang sử dụng phiên bản Netty nào? – HCarrasko

+0

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

+0

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

Trả lời

1

Có lẽ nó liên quan với vấn đề này Netty https://github.com/netty/netty/issues/1731

này dự kiến ​​hành vi, và không có gì có thể thay đổi. JVM báo hiệu rằng nó không thể chấp nhận kênh - do đó không thể kết nối và không thể gửi phản hồi. Máy khách sẽ thấy lỗi kết nối. Nếu bạn có bộ cân bằng tải, cần thử lại với máy chủ lưu trữ thay thế hoặc trả lại số 503 trên số ứng dụng của bạn.

Các vấn đề liên quan