netty4 epoll AdaptiveRecvByteBuf不自动调整大小?

时间:2016-06-14 11:23:36

标签: java udp netty epoll

我收到了netty4.0作为水槽源的udp数据,使用本地传输,替换为Epoll *类。 我使用AdaptiveRecvByteBufAllocator设置了EpollChannelOption,但是recvbuffer没有自动调整大小。它总是丢失一些数据。我做错了什么?感谢

@Override
public void start() {

    ExecutorService threadPool = Executors.newFixedThreadPool(maxThreads);

    group = new EpollEventLoopGroup();

    sourceCounter.start();

    try {
        Bootstrap serverBootstrap = new Bootstrap();

        serverBootstrap.group(group).channel(EpollDatagramChannel.class)
                .option(EpollChannelOption.SO_RCVBUF, 65536)
                .option(EpollChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(200,65536,65536))
                //.option(EpollChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(65536))
                .option(EpollChannelOption.SO_REUSEPORT, true)
                .handler(new UDPChannelHandler(maxSize, delimiter, threadPool));

        //get Processors number
        int updworkerThreads = Runtime.getRuntime().availableProcessors();
        logger.info("availableProcessors is" + updworkerThreads);
        for (int i = 0; i < updworkerThreads; ++i) {
            ChannelFuture future = serverBootstrap.bind(new InetSocketAddress(host, port)).await();

            if (!future.isSuccess()) {
                logger.error(String.format("Fail to bind on port = %d.",
                        port), future.cause());
            } else {
                logger.info(String.format("success to bind on port = %d,count %d times.",
                        port, i + 1));
            }
        }
        sourceCounter.setOpenConnectionCount(updworkerThreads);
    } catch (InterruptedException ex) {
        logger.error("listen SO_REUSEPORT port " + port + "error:", ex);
    }

    super.start();

}

@Override
public void stop() {
    logger.info("UDP Source stopping...");
    logger.info("Metrics:{}", counterGroup);
    if (group != null) {
        group.shutdownGracefully();
    }

    sourceCounter.stop();
    super.stop();
}



class HandleTask implements Runnable {
    ByteBuf msg;
    String remoteIP;

    public HandleTask(ByteBuf msg,String remoteIp) {
        this.msg = msg;
        this.remoteIP = remoteIp;
    }

    public void run() {
        try {
            Event e = buildEvent(msg);
            if (e == null) {
                logger.info("build event is null");
                return;
            }
            getChannelProcessor().processEvent(e);
            counterGroup.incrementAndGet("events.success");
            sourceCounter.incrementAppendAcceptedCount();
            sourceCounter.incrementEventAcceptedCount();
        } catch (ChannelException ex) {
            counterGroup.incrementAndGet("events.dropped");
            logger.error("Error writting to channel", ex);
            return;
        }
    }






// class to handle incoming Netty message events.
@ChannelHandler.Sharable
public class UDPChannelHandler extends SimpleChannelInboundHandler<DatagramPacket> {
    protected int maxSize;
    protected char delimiter;
    protected boolean isIncompleteEvent;
    private ExecutorService threadPool;

    public UDPChannelHandler(int maxSize, char delimiter, ExecutorService threadPool) {
        super();

        this.maxSize = maxSize;
        this.delimiter = delimiter;
        this.isIncompleteEvent = false;

        this.threadPool = threadPool;
    }


    @Override
    public void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet)
            throws Exception {

   /*
     * ChannelBuffer buf = (ChannelBuffer)e.getMessage(); byte[] des =
     * buf.array(); String recvText = new String(des, 0, des.length);
     * System.out.println(recvText); Channel ch = e.getChannel();
     * ch.write(e.getMessage());
     */

        //List<Integer> data = (List<Integer>) e.getMessage();
        //ByteBuf data = (ByteBuf) packet.content();
        //logger.info("channelRead0! " + new String(data.));

        sourceCounter.incrementEventReceivedCount();
        sourceCounter.incrementAppendReceivedCount();
        ByteBuf data = Unpooled.copiedBuffer(packet.content());
        String remoteIp = packet.sender().getAddress().getHostAddress();
        HandleTask ht = new HandleTask(data,remoteIp);
        threadPool.submit(ht);

        //String content = String.format("client: %d, index: %d, a: %d, b: %d", clientNo, index, a, b);
        //System.out.println(content);

    }

}

1 个答案:

答案 0 :(得分:0)

对于UDP,netty使用FixedRecvByteBufAllocator(默认缓冲区大小为2048)作为默认值。即使您使用AdaptiveRecvByteBufAllocator,netty也不会尊重它。

Netty以不同的方式使用RecvByteBufAllocator进行TCP和UDP。对于TCP额外工作(调用recordreadComplete),可以猜测最佳缓冲区大小。

如果netty尊重UDP的AdaptiveRecvByteBufAllocator,则事件可能会在猜出最佳大小之前丢失数据。