私はNettyが初めてです。現在、サーバーを移行しているため、高負荷が発生しています。例のようにすべてを実行して、多くの人を読みましたが、バグがあります。CPU負荷が時間とともに非常に速く増加します。
ヒープとログを分析すると、例外をスローするチャネル (それらだけではない可能性があります) が正常に閉じず、ワーカーのセレクターに保持されることがわかります。50 人のユーザーがオンラインで 150 以上のチャンネルを開設しました。
私のコードは次のとおりです。
サーバーの作成:
networkServer = new ServerBootstrap(new NioServerSocketChannelFactory(bossExec, ioExec, 4));
networkServer.setOption("backlog", 500);
networkServer.setOption("connectTimeoutMillis", 10000);
networkServer.setPipelineFactory(new ServerPipelineFactory());
Channel channel = networkServer.bind(new InetSocketAddress(address, port));
パイプライン工場:
@Override
public ChannelPipeline getPipeline() throws Exception {
PacketFrameDecoder decoder = new PacketFrameDecoder();
PacketFrameEncoder encoder = new PacketFrameEncoder();
return Channels.pipeline(decoder, encoder, new PlayerHandler(decoder, encoder));
}
デコーダ:
public class PacketFrameDecoder extends FrameDecoder {
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
}
@Override
protected Object decode(ChannelHandlerContext arg0, Channel arg1, ChannelBuffer buffer) throws Exception {
try {
buffer.markReaderIndex();
Packet p = // ... doing decoding things
if(p != null)
return p;
// Reset buffer if not success
buffer.resetReaderIndex();
// Reset buffer if not success and got exception of not enough bytes in buffer
} catch(BufferUnderflowException e) {
buffer.resetReaderIndex();
} catch(ArrayIndexOutOfBoundsException aioobe) {
buffer.resetReaderIndex();
}
return null;
}
}
そしてハンドラー:
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
worker = new PlayerWorkerThread(this, e.getChannel());
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
worker.disconnectedFromChannel();
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
if(e.getChannel().isOpen())
worker.acceptPacket((Packet) e.getMessage());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
Server.logger.log(Level.WARNING, "Exception from downstream", e.getCause());
ctx.getChannel().close();
}
CPU負荷の増加を除いて、すべてが非常にうまく機能しています...