Netty ChannelPool

ChannelPool

Many of our users needed to support connection pooling at some point when they used Netty to writing a client. This resulted in a lot of duplicated code. With the release of 4.0.28.Final we include a pool API that users can use to implement there own ChannelPool or reuse either the SimpleChannelPool or the FixedChannelPool that are provided by Netty itself.java

EventLoopGroup group = new NioEventLoopGroup();
final Bootstrap cb = new Bootstrap();
InetSocketAddress addr1 = new InetSocketAddress("10.0.0.10", 8888);
InetSocketAddress addr2 = new InetSocketAddress("10.0.0.11", 8888);

cb.group(group).channel(NioSocketChannel.class);

ChannelPoolMap<InetSocketAddress, SimpleChannelPool> poolMap = new AbstractChannelPoolMap<InetSocketAddress, SimpleChannelPool>() {
    @Override
    protected SimpleChannelPool newPool(InetSocketAddress key) {
        return new SimpleChannelPool(cb.remoteAddress(key), new TestChannelPoolHandler());
    }
};

// depending on when you use addr1 or addr2 you will get different pools.
final SimpleChannelPool pool = poolMap.get(addr1);
Future<Channel> f = pool.acquire();
f.addListener(new FutureListener<Channel>() {
    @Override
    public void operationComplete(Future<Channel> f) {
        if (f.isSuccess()) {
            Channel ch = f.getNow();
            // Do somethings
            // ...
            // ...

            // Release back to pool
            pool.release(ch);
        }
    }
});

The important thing to note is that your key could be everything. This makes it very flexible... For example you could have different pools for different EventLoops etc.linux

Please refer to the api documentation in the io.netty.transport.pool package.api

Splice

This release includes support for splice when using the native epoll transport. Splicing allows to directly transfer bytes from one filedescriptor to another without copy data from kernel to user-space. This makes splice a perfect fit i.e when you want to write a TCP proxy.tcp

The following code snipped shows a full TCP proxy that uses splicing:ide

EventLoopGroup group = new EpollEventLoopGroup(1);
ServerBootstrap bs2 = new ServerBootstrap();
bs2.channel(EpollServerSocketChannel.class);
bs2.childOption(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
bs2.group(group).childHandler(new ChannelInboundHandlerAdapter() {
    @Override
    public void channelActive(final ChannelHandlerContext ctx) throws Exception {
        ctx.channel().config().setAutoRead(false);
        Bootstrap bs = new Bootstrap();
        bs.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);

        bs.channel(EpollSocketChannel.class);
        bs.group(ctx.channel().eventLoop()).handler(new ChannelInboundHandlerAdapter() {
            @Override
            public void channelActive(ChannelHandlerContext context) throws Exception {
                final EpollSocketChannel ch = (EpollSocketChannel) ctx.channel();
                final EpollSocketChannel ch2 = (EpollSocketChannel) context.channel();
                // We are splicing two channels together, at this point we have a tcp proxy which handles all
                // the data transfer only in kernel space!

                // Integer.MAX_VALUE will splice infinitly.
                ch.spliceTo(ch2, Integer.MAX_VALUE).addListener(new ChannelFutureListener() {
                    @Override
                    public void operationComplete(ChannelFuture future) throws Exception {
                        if (!future.isSuccess()) {
                            future.channel().close();
                        }
                    }
                });
                // Trigger multiple splices to see if partial splicing works as well.
                ch2.spliceTo(ch, SPLICE_LEN).addListener(new ChannelFutureListener() {
                    @Override
                    public void operationComplete(ChannelFuture future) throws Exception {
                        if (!future.isSuccess()) {
                            future.channel().close();
                        } else {
                            ch2.spliceTo(ch, SPLICE_LEN).addListener(this);
                        }
                    }
                });
                ctx.channel().config().setAutoRead(true);
            }

            @Override
            public void channelInactive(ChannelHandlerContext context) throws Exception {
                context.close();
            }
        });
        bs.connect(new InetSocketAddress("10.0.0.10", 8888)).addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                if (!future.isSuccess()) {
                    ctx.close();
                } else {
                    future.channel().closeFuture().addListener(new ChannelFutureListener() {
                        @Override
                        public void operationComplete(ChannelFuture future) throws Exception {
                            ctx.close();
                        }
                    });
                }
            }
        });
    }
});
Channel pc = bs2.bind(new InetSocketAddress(0)).syncUninterruptibly().channel();

Beside this we also support splicing directly to a file. For more informations please refer to the AbstractEpollStreamChannel javadocs.oop

As always, please let us know if you find any issues. We love feedback!flex

相關文章
相關標籤/搜索