Netty是一个业界使用范围特别广的高并发线程框架,关于线程模型框架,可以说直接影响着网络程序的性能

为什么使用Netty,Netty带了的性能提升有哪些,主要就这两个方面进行解答

1.网络编程的性能瓶颈,在之前的网络编程中,客户端和服务端建立了一个连接,这个连接是传统的BIO,也就是阻塞式的IO,会为每一个Socket分配一个独立的线程

虽然保证了网络编程的安全性,但是会导致一个网络请求对应一个线程,如果响应速度或发送速度过慢,都会导致线程的阻塞,而且需要考虑一个问题,就是在于连接建立了之后,如果请求迟迟不到,也会导致阻塞问题的出现

图片

在现实生活中,往往在十万乃至百万并发问题时候,如果采用这种阻塞式的IO操作,需要服务器端提供相对应数量的线程,这几乎等于是不可能的

故,Java提供了非阻塞式的NIO的API.使用非阻塞式的API来做到一个线程处理多个请求了,而且外加上 Reactor设计模式,实现了Netty

接下来先说明下Reactor模式

图片

上面为其的类图

其中Handle值得就是IO句柄,就是一个网络连接的抽象画,Event Handler作为事件处理器,可以调用其的handle_event()方法处理IO事件,

Synchronous Event Demutiplexer是系统提供的多路复用API

Reactor模式的核心是Reactor这个类,其中register_handler是用于阻塞处理器,handle_events()用于返回所有的处理器,然后遍历来选择处理器处理

所以通常都是while(true){}来调用handle_events()方法

Netty中的线程模型

在Reactor的基础之上,发展出了自己的套路,其核心的概念就是事件循环 EventLoop, 负责监听事件并调用事件处理器

在Netty中,事件处理器和网络连接是一对多的关系,而EventLoop和Java线程是一对一的关系

这里的稳定是关系的一旦确定就不再变化,也就是一个网络连接对应一个EventLoop,保证了单线程,确保了处理安全

图片

其还有一个核心概念,EventLoopGroup,一个EventLoopGroup由一组EventLoop组成

实际使用中,往往有两组EventLoopGroup,称为BossGroup WorkGroup

这两个Group的分工明确,因为在TCP网络请求中,会建立两个Socket,一个用于连接请求,一个用于处理请求,建立两个请求,所以会创建两个Socket,对应着创建两个Group,在Netty中,Boss用于分配连接请求,Work用于真正的处理请求

两者用轮询算法连接

在真正的使用中,需要注意的是,如果Boss只监听一个端口,那么只需要一个EventLoop

在默认情况下,Netty会创建2*CPU核数的EventLoop,但是仍然需要避免长时间的阻塞问题

如果想要对Netty深入的了解,可以去学习一些TCP/IP的网络知识,参考<<TCP/IP网络编程>>

public static void main(String[] args) {

//事件处理器

final EchoServerHandler serverHandler = new EchoServerHandler();

//boss线程组

EventLoopGroup bossGroup = new NioEventLoopGroup(1);

//worker线程组

EventLoopGroup workerGroup = new NioEventLoopGroup();

try {

ServerBootstrap b = new ServerBootstrap();

b.group(bossGroup, workerGroup)

.channel(NioServerSocketChannel.class)

.childHandler(new ChannelInitializer<SocketChannel>() {

@Override

public void initChannel(SocketChannel ch){

ch.pipeline().addLast(serverHandler);

}

});

//bind服务端端口

ChannelFuture f = b.bind(9090).sync();

f.channel().closeFuture().sync();

} finally {

//终止工作线程组

workerGroup.shutdownGracefully();

//终止boss线程组

bossGroup.shutdownGracefully();

}

}

//socket连接处理器

class EchoServerHandler extends ChannelInboundHandlerAdapter {

//处理读事件

@Override

public void channelRead(ChannelHandlerContext ctx, Object msg){

ctx.write(msg);

}

//处理读完成事件

@Override

public void channelReadComplete(ChannelHandlerContext ctx){

ctx.flush();

}

//处理异常事件

@Override

public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {

cause.printStackTrace();

ctx.close();

}

}

发表评论

邮箱地址不会被公开。 必填项已用*标注