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
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