由于公司线上netty服务出现java.io.IOException: Too many open files的报错。为了找出问题、解决问题经过多天的研究,记录研究过程中了解到的一些知识。通过阅读本文将了解下面几个问题:
-
假如当服务支持4000TPS,而请求并发为6000TPS时,会出现什么情况?会不会导致服务崩溃?
-
当出现 Too many open files,只加大系统的文件的句柄数能否解决问题?
-
一个tcp连接会占用一个文件句柄,通过netstat命令查看端口的所有状态的连接数明明远少于通过ulimit -n显示的文件句柄数,但系统依然报 Too many open files?
-
netty服务端跟客户端已经建立连接,但当客户端非正常关闭时,netty服务器会不会立即释放文件句柄?
阅读下面内容时,请先认真思考以上问题。本文将用到netty的测试服务,jmeter压测工具
netty服务
编写一个简单的http服务器
public class HttpPipeline extends ChannelInitializer<SocketChannel> {
@Autowired
HttpServerHandler httpServerHandler;
@Override
public void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
p.addLast(new HttpServerCodec());
p.addLast(new HttpContentCompressor());
// HttpObjectAggregator:将HTTP消息的多个部分合成一条完整的HTTP消息
p.addLast(new HttpObjectAggregator(1048576));
// http请求根处理器
p.addLast(httpServerHandler);
}
}
@Component
@Slf4j
@ChannelHandler.Sharable //@Sharable 注解用来说明ChannelHandler是否可以在多个channel直接共享使用
public class HttpServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
try {
Thread.sleep(30000);
FullHttpResponse fullHttpResponse = buildResponse("success");
ctx.writeAndFlush(fullHttpResponse).addListener((channel)->{
log.error("send successed");
ctx.close();
});
//负责显式释放与池的ByteBuf实例相关联的内存,SimpleChannelInboundHandler会自动释放资源,因此无需显式释放
ReferenceCountUtil.release(msg);
} catch (Exception e) {
log.error("system exception:{}", e);
}
}
/**
* 构建响应对象
* @return
*/
private FullHttpResponse buildResponse(String msg) {
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
HttpResponseStatus.valueOf(200), Unpooled.wrappedBuffer(msg.getBytes()));
HttpHeaders headers = response.headers();
//headers.set(HttpHeaderNames.TRANSFER_ENCODING, HttpHeaderValues.CHUNKED);
//headers.set(HttpHeaderNames.CONTENT_TYPE, new AsciiString("application/json; charset=utf-8"));
return response;
}
/**
* 当客户端断开连接
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
ctx.close();
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
}
}
public class HttpServer {