当server相应client的请求时,有时候需要server作为client向其他server请求资源,这个时候一般通过再创建新的bootstrap,添加新的EventLoopgroup,,这种做法创建新的线程,会有线程创建和切换的开销,并且会有client 线程和server线程的数据交换,所有可以通过将server的EventLoop Group到client的bootstrap中,这样实现线程复用。
import java.net.InetSocketAddress;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
/**
* 当处理client的请求时,需要server作为client向其他server请求,这时这个server作为client,因为一个EventLoop为一个线程,共享EventLoop不需要创建新的线程,没有上下文切换的开销,server作为另一个client,没有数据传输的问题。
* @author pc
*
*/
public class BootstrapEventLoopGroup {
public void bootstrap(){
NioEventLoopGroup group = new NioEventLoopGroup();
try{
ServerBootstrap boot = new ServerBootstrap();
boot.group(group)
.channel(NioServerSocketChannel.class)// 指定channel为NioServerSocketChannel
.childHandler(new SimpleChannelInboundHandler<ByteBuf>(){
ChannelFuture future;
@Override
public void channelActive(ChannelHandlerContext ctx ){
System.out.println("连接成功!");
// 将server已经存在的EventLoop传入server 作为client的EventLoopGroup。不用新建EventGroup。
Bootstrap client = new Bootstrap();
client.group(ctx.channel().eventLoop());// 将server的EventLoop传递给client的group。这样可以不用创创建新的开销。
client.channel(NioSocketChannel.class);
future = client.connect(new InetSocketAddress("www.manning.com" , 80));
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
// TODO Auto-generated method stub
if (future.isDone()){// 如果server作为client已经连接好了。
}
}
});
ChannelFuture future = boot.bind(new InetSocketAddress(8000));// 绑定到指定端口
future.addListener(new ChannelFutureListener(){
@Override
public void operationComplete(ChannelFuture future) throws Exception {
// TODO Auto-generated method stub
if (future.isDone()){
System.out.println("server complete.");
}
}
});
} finally{
}
}
}
在引导过程中添加多个ChannelHandler。
channelInitializer可以向pipeline添加多个ChannelHandler,向channel注册实现ChannelInitializer的实例,之后会调用override的initChannel()的方法,通过向channel添加多个channelHandler。
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;
public class BootstrapWithInitializer {
public void boostrap(){
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(new NioEventLoopGroup() , new NioEventLoopGroup() )
.channel(NioServerSocketChannel.class)// 指定channel
.childHandler(new InitializerImp());// 注册channelInitializer,设置多个channelHandler。
}
// 设置initializerImp自定义的channelHandler。
private class InitializerImp extends ChannelInitializer<Channel>{
@Override
protected void initChannel(Channel ch) throws Exception {
// TODO Auto-generated method stub
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new HttpClientCodec());
pipeline.addLast(new HttpObjectAggregator(Integer.MAX_VALUE));
}
}
}
通过设置simpleChannelInboundHandler<DatagramPacket>设置Netty为无连接请求。