DotNetty
DotNetty copied to clipboard
When high concurrency under counter problems
My business code is to implement ChannelHandlerAdapter, and then convert msg to Byte[], and when parsing byte byte arrays at high concurrency, there will be reference counter exceptions System.ArgumentOutOfRangeException: Count must be positive and count must refer to a location within the string/array/collection. Parameter name: count at System.Array.IndexOf[T](T[] array, T value, Int32 startIndex, Int32 count) at System.Collections.Generic.Queue`1.Contains(T item)
`public class SocketByteHandler: ChannelHandlerAdapter {
readonly bool autoRelease;
public SocketByteHandler() : this(true)
{
}
protected SocketByteHandler(bool autoRelease)
{
this.autoRelease = autoRelease;
}
public bool AcceptInboundMessage(object msg) => msg is IByteBuffer;
public override void ChannelRead(IChannelHandlerContext ctx, object msg)
{
bool release = true;
try
{
if (this.AcceptInboundMessage(msg))
{
IByteBuffer imsg = (IByteBuffer)msg;
byte[] result = new byte[imsg.ReadableBytes];
imsg.ReadBytes(result,0,imsg.ReadableBytes);
this.ChannelRead0(ctx, result);
}
else
{
release = false;
ctx.FireChannelRead(msg);
}
}
finally
{
if (autoRelease && release)
{
ReferenceCountUtil.Release(msg);
}
}
}
protected virtual void ChannelRead0(IChannelHandlerContext ctx,byte[] msg)
{
}
}`
`public void Init(ServerOptions options,Func<IChannelHandler> handler) { _options = options; if (options.EventLoopCount > 0) { bossGroup = new MultithreadEventLoopGroup(options.EventLoopCount); } else { bossGroup = new MultithreadEventLoopGroup(); } workerGroup = new MultithreadEventLoopGroup(); bootstrap = new ServerBootstrap(); bootstrap.Group(bossGroup, workerGroup); bootstrap.Channel<TcpServerSocketChannel>();
bootstrap.Option(ChannelOption.SoBacklog, _options.SoBacklog);
bootstrap.ChildOption(ChannelOption.RcvbufAllocator,new AdaptiveRecvByteBufAllocator(64,1048,65536));
bootstrap.Option(ChannelOption.TcpNodelay, true);
bootstrap.ChildOption(ChannelOption.SoKeepalive, false);
bootstrap.ChildHandler(new ActionChannelInitializer<ISocketChannel>(channel =>
{
IChannelPipeline pipeline = channel.Pipeline;
pipeline.AddLast(new MTFrameDecoder(ByteOrderEnum.LittleEndian, AppConfig.ServerOptions.MaxPackLength, AppConfig.ServerOptions.HeadPosition, AppConfig.ServerOptions.HeadLength
, AppConfig.ServerOptions.LengthAdjustment, 0, true));
//pipeline.AddLast(new IdleStateHandler(300, 300, 0));
if (options.ReadTimeout > 0)
{
pipeline.AddLast("ReadTimeout", new ReadTimeoutHandler(options.ReadTimeout));
}
pipeline.AddLast(handler());
}));
}`
It not an reference counter exception. In fact System.Collections.Generic.Queue<T>
is not thread-safe and can not be used concurrently.
And what's the full stacktrace, looks like an exception in other code. DotNetty only use Queue<T>
in DotNetty.Codecs.Http
,DotNetty.Handlers.Streams.ChunkedWriteHandler<T>
and EmbeddedChannel
It's supposed to be my business code problem, thank you.