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.

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.

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

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.

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

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.

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

转载于:https://my.oschina.net/u/1469495/blog/718256

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值