而一个 EventLoop 也只会对应到一个 Java 线程
标签:
Netty 是一个高性能的网络框架,应用非常遍及,目前在Java 范围,Netty 根基上成为网络措施的标配了,Netty 框架成果丰富,也非常庞大。今天主要分析Netty 框架中的线程模型,而线程模型直接影响着网络措施的性能。在介绍Netty 的线程模型之前,我们首先搞清楚网络编程性能的瓶颈在哪里,然后再看Netty 的线程模型是如何解决这个问题的。
网络编程性能的瓶颈传统的BIO 编程模型里, 所有的read() 操纵和 write() 操纵城市梗阻当前线程的, 如果客户端和处事端已经成立了一个连接,而迟迟不发送数据,那么处事真个 read() 操纵会一直梗阻, 所以使用BIO 模型, 一般城市为每个socket 分配一个独立的线程,这样就不会因为线程梗阻在一个socket 上而影响对其他socket 的读写。
BIO 的线程模型如下图所示:每个socket 对应一个独立的线程。为了制止频繁创建消耗线程,可以给与线程池,但是socket 和线程之间的对应关系不会变革。
BIO 这种线程模型,适用于socket 连接不是很多的场景。但是此刻的互联网场景,往往需要处事器能够支撑十万甚至百万连接,而创建十万甚至百万连接显然不现实,所以BIO 线程模型无法解决百万连接的问题。如果仔细不雅察看,你会发明互联网场景中,虽然连接很多,但是每个连接的请求并不频繁,所以线程大部分时间都在期待I/O 就绪,也就是说线程大部分时间都梗阻在那里,这完全是浪费,如果我们能够解决这个问题,那就不需要这么多线程了。
顺着这个思路,我们可以将线程的模型优化为下图这个样子,用一个线程来措置惩罚惩罚多个连接,这样操作率就上来了,同时所需要的线程数量也降下来了。可是使用 BIO 相关的 API 是无法实现的, 为什么呢?因为 BIO 相关的 socket 读写操纵都是梗阻式的,而一旦挪用了梗阻式 API,在 I/O 就绪前,挪用线程会一直梗阻,也就无法措置惩罚惩罚其他的 socket 连接了。
好在 Java 里还供给了非梗阻式(NIO)API, 操作非梗阻API 就能够实现一个线程措置惩罚惩罚多个连接了。 那具体如何实现呢?此刻遍及给与的都是Reactor 模式, 包孕Netty 的实现,所以先让我们了解以下 Reactor 模式。
Reactor 模式下面是 Reactor 模式的类布局图,此中 Handle 指的是 I/O 句柄,在 Java 网络编程里,它素质上就是一个网络连接。Event Handler 很容易理解,就是一个事件措置惩罚惩罚器,此中 handle_event() 要领措置惩罚惩罚 I/O 事件,也就是每个 Event Handler 措置惩罚惩罚一个 I/O Handle;get_handle() 要领可以返回这个 I/O 的 Handle。Synchronous Event Demultiplexer 可以理解为操纵系统供给的 I/O 多路复用 API,例如 POSIX 标准里的 select() 以及 Linux 里面的 epoll()。
Reactor 模式的核心自然是 Reactor 这个类,此中 register_handler() 和 remove_handler() 这两个要领可以注册和删除一个事件措置惩罚惩罚器;handle_events() 方法是核心,也是 Reactor 模式的策动机,这个要领的核心逻辑如下:首先通过同步事件多路选择器供给的 select() 要领监听网络事件,当有网络事件就绪后,就遍历事件措置惩罚惩罚器来措置惩罚惩罚该网络事件。由于网络事件是源源不停的,所以在主措施中启动 Reactor 模式,,需要以 while(true){} 的方法挪用 handle_events() 要领。
void Reactor::handle_events(){ //通过同步事件多路选择器供给的 //select()要领监听网络事件 select(handlers); //措置惩罚惩罚网络事件 for(h in handlers){ h.handle_event(); } } // 在主措施中启动事件循环 while (true) { handle_events(); Netty 中的线程模型Netty 的实现虽然参考了 Reactor 模式,但是并没有完全照搬,Netty 中最核心的观点是事件循环(EventLoop),其实也就是 Reactor 模式中的 Reactor,卖力监听网络事件并挪用事件措置惩罚惩罚器进行措置惩罚惩罚。在 4.x 版本的 Netty 中,网络连接和 EventLoop 是不变的多对 1 关系,而 EventLoop 和 Java 线程是 1 对 1 关系,这里的不变指的是关系一旦确定就不再产生变革。也就是说一个网络连接只会对应独一的一个 EventLoop,而一个 EventLoop 也只会对应到一个 Java 线程,所以一个网络连接只会对应到一个 Java 线程。
一个网络连接对应到一个 Java 线程上,有什么好处呢?最大的好处就是对付一个网络连接的事件措置惩罚惩罚是单线程的,这样就制止了各类并发问题。
Netty 中的线程模型可以参考下图,这个图和前面我们提到的抱负的线程模型图非常相似,核心方针都是用一个线程措置惩罚惩罚多个网络连接。
温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/web/30602.html