netty示例
maven依赖
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.22.Final</version>
</dependency>
echo服务器示例
public class EchoServer {
private int port;
public EchoServer(int port){
this.port = port;
}
public void run() throws Exception{
//bossGroup只负责接收客户端的连接,不做复杂操作,为了减少资源占用,取值越小越好
EventLoopGroup bossGroup=new NioEventLoopGroup(1, new DefaultThreadFactory("netty-acceptor"));
//workerGroup作为worker,处理boss接收的连接的流量和将接收的连接注册进入这个worker
EventLoopGroup workerGroup=new NioEventLoopGroup(Math.max(1, Runtime.getRuntime().availableProcessors()-1), new DefaultThreadFactory("netty-worker"));
//longBizGroup作为耗时业务处理器
EventLoopGroup longBizGroup = new NioEventLoopGroup(100, new DefaultThreadFactory("netty-long-worker"));
try {
ServerBootstrap b=new ServerBootstrap(); //ServerBootstrap负责建立服务端
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class) //指定使用NioServerSocketChannel产生一个ServerChannel用来接收连接,会在使用bossGroup的EventLoop中执行
.childHandler(new ChannelInitializer<SocketChannel>() {//ChannelInitializer用于配置一个新的Channel用来处理数据读写,以及业务操作等
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline(); //处理器管道
pipeline.addLast(longBizGroup, new EchoServerHandler()); //配置自定义的处理器,并在指定的longBizGroup的EventLoop中执行
};
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f=b.bind(port).sync();
f.channel().closeFuture().sync();
}finally{
bossGroup.shutdownGracefully(); //资源优雅释放
workerGroup.shutdownGracefully();
}
}
public static class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
TimeUnit.MILLISECONDS.sleep(50); //模拟耗时任务
ctx.write(msg); //调用write方法来逐字返回接收到的信息
ctx.flush(); //只调用write是不会释放的,它会缓存,直到调用flush
//ctx.writeAndFlush(msg); //可以直接使用writeAndFlush(msg)
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
public static void main(String[] args) {
int port=8088;
try {
new EchoServer(port).run();
} catch (Exception e) {
e.printStackTrace();
}
}
}
echo服务器测试
telnet localhost 8088
hello
hello
IO模型
IO模型列表.pngBIO模型
BIO模型.png
伪异步IO
伪异步IO.pngNIO模型
NIO模型.png基于NIO模型,可以演变出以下四种reactor模型:
一、Reactor单线程模型: Reactor线程负责Accept新连接,网络IO,并分派请求到处理器中执行。
image.png
对应的netty配置
EventLoopGroup reactorGroup = new NioEventLoopGroup(1);
serverBootstrap.group(reactorGroup,reactorGroup);
二、Reactor单线程+线程池模型: Reactor线程负责Accept新连接,网络IO;线程池负责处理器执行。
image.png对应的netty配置
EventLoopGroup reactorGroup = new NioEventLoopGroup(1);
serverBootstrap.group(reactorGroup,reactorGroup);
EventLoopGroup bizGroup = new NioEventLoopGroup(100);
pipeline.addLast(bizGroup, new XxxChannelHandler());
三、主从Reactor模型:主Reactor线程负责Accept新连接,从Reactor负责网络IO和处理器执行。
image.png
对应的netty配置
EventLoopGroup acceptorGroup = new NioEventLoopGroup(1);
EventLoopGroup ioGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors());
serverBootstrap.group(acceptorGroup,ioGroup);
四、主从Reactor+ 线程池模型: 主Reactor线程负责Accept新连接,从Reactor负责网络IO,线程池负责处理器执行。
image.png
对应的netty配置
EventLoopGroup acceptorGroup = new NioEventLoopGroup(1);
EventLoopGroup ioGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors());
serverBootstrap.group(acceptorGroup,ioGroup);
EventLoopGroup bizGroup = new NioEventLoopGroup(100);
pipeline.addLast(bizGroup, new XxxChannelHandler());
netty的EventLoop与Channel
netty的BIO模型下的EventLoop分配
image.pngnetty的NIO模型下的EventLoop分配
image.pngEventLoop执行逻辑
image.png
网友评论