您的位置 首页 java

Java并发——Netty线程模型

BIO

1.BIO即阻塞式IO,使用BIO模型,一般会为每个Socket分配一个独立的线程

  • 为了避免频繁创建和销毁线程,可以采用线程池,但Socket和线程之间的对应关系不会发生变化

2.BIO适用于Socket连接不是很多的场景,但现在上百万的连接是很常见的,而创建上百万个线程是不现实的

  • 因此BIO线程模型无法解决百万连接的问题

3.在互联网场景中,连接虽然很多,但每个连接上的请求并不频繁,因此线程大部分时间都在等待IO就绪

理想的线程模型

1.用一个线程来处理多个连接,可以提高线程的利用率,降低所需要的线程

2.使用BIO相关的API是无法实现的,BIO相关的Socket读写操作都是阻塞式的

  • 一旦调用了阻塞式的API,在IO就绪前,调用线程会一直阻塞,也就无法处理其他的Socket连接

3.利用NIO相关的API能够实现一个线程处理多个连接,通过Reactor模式实现

Reactor模式

1.Handle指的是IO句柄,在 Java 网络编程里,本质上是一个 网络连接

2.Event Handler是事件处理器,handle_event()处理IO事件, 每个Event Handler处理一个IO Handle

  • get_handle()方法可以返回这个IO Handle
  1. Synchronous Event Demultiplexer相当于操作系统提供的 IO多路复用API
  • 例如POSIX标准里的 select() 以及Linux里的 epoll ()

4.Reactor是Reactor模式的核心

  • register_handler()和remove_handler()可以注册和删除一个事件处理器
  • handle_events()是核心
  • 通过同步事件多路选择器提供的select()方法 监听网络事件
  • 当有网络事件就绪后,就 遍历事件处理器 来处理该网络事件
void Reactor::handle_events(){
 // 通过同步事件多路选择器提供的select()方法监听网络事件
 select(handlers);
 // 处理网络事件
 for(h in handlers){
 h.handle_event();
 }
}
// 在主程序中启动事件循环
while (true) {
 handle_events();
}
 

Netty 的线程模型

1.Netty参考了Reactor模式,Netty中最核心的概念是 事件循环 (EventLoop),即Reactor模式中的Reactor

  • 负责监听网络事件并调用事件处理器进行处理
  1. 在Netty 4.x中,网络连接 : EventLoop : Java线程 = N:1:1
  • 所以, 一个网络连接只会对应到一个Java线程
  • 优点:对于一个网络连接的事件处理都是 单线程 的,这样能 避免各种并发问题

EventLoopGroup

1.EventLoopGroup由一组EventLoop组成

  • 实际使用中,一般会创建两个EventLoopGroup,一个是bossGroup,一个是workerGroup

2.Socket处理 TCP 网络连接请求,是在一个独立的Socket中

  • 每当有一个TCP连接成功建立,都会创建一个新的Socket
  • 之后对TCP连接的读写都是由新创建处理的Socket完成的
  • 处理TCP连接请求和读写请求是通过两个不同的Socket完成的

3.在Netty中,bossGroup用来处理连接请求的,workerGroup用来处理读写请求的

  • bossGroup处理完连接请求后,会将这个连接提交给workerGroup来处理
  • workerGroup中会有多个EventLoop,通过均衡负载算法(轮询)来分配某一个EventLoop

Echo程序

public class Echo {
 public static void main(String[] args) {
 // 事件处理器
 EchoServerHandler serverHandler = new EchoServerHandler();
 // boss线程组
 EventLoopGroup bossGroup = new NioEventLoopGroup(1);
 // worker线程组
 EventLoopGroup workerGroup = new NioEventLoopGroup(1);
 try {
 ServerBootstrap bootstrap = new ServerBootstrap();
 bootstrap.group(bossGroup, workerGroup)
 . channel (NioServerSocketChannel.class)
 .childHandler(new ChannelInitializer<SocketChannel>() {
 @ Override 
 protected void initChannel(SocketChannel socketChannel) throws Exception {
 socketChannel.pipeline().addLast(serverHandler);
 }
 });
 // 绑定端口号
 Channel future  future = bootstrap. bind (9090).sync();
 future.channel().closeFuture().sync();
 } catch (InterruptedException e) {
 e.printStackTrace();
 } finally {
 // 终止worker线程组
 workerGroup.shutdownGracefully();
 // 终止boss线程组
 bossGroup.shutdownGracefully();
 }
 }
}
// Socket连接处理器
class EchoServerHandler extends ChannelInboundHandlerAdapter {
 // 处理读事件
 @Override
 public void channelRead(ChannelHandlerContext ctx, Object  msg ) throws Exception {
 ctx.write(msg);
 }
 // 处理读完成事件
 @Override
 public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
 ctx.flush();
 }
 // 处理异常事件
 @Override
 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
 cause.printStackTrace();
 ctx.close();
 }
}
 

写在最后

文章来源:智云一二三科技

文章标题:Java并发——Netty线程模型

文章地址:https://www.zhihuclub.com/200952.shtml

关于作者: 智云科技

热门文章

发表回复

您的电子邮箱地址不会被公开。

网站地图