Netty中的常见问题
Posted 码农的修炼之道
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Netty中的常见问题相关的知识,希望对你有一定的参考价值。
最近,一些小伙伴问我一些关于Netty的常见的问题。今天先详细介绍第一个常见的问题:
Netty中的线程模型有哪些,它们之间有什么区别吗?
我们之前的一篇文章简单的介绍了netty中采用了Reactor线程模型,所谓的Reactor模型,就是多路复用模型。可以参考下面的文章了解一下。
《》
简单的说,一共有三种线程模型:单Reactor模型、多Reactor模型、主从Reactor模型。其主要区别是:
(1)单Reactor线程模型。这种方式就是启动一个线程,这个线程既监听客户端的连接,也处理这个连接的IO流,类似于我们传统的OIO编程,这样每次来一个客户端服务端就启动一个线程来服务这个客户端。
(2)多Reactor线程模型。就是单独启动一个线程来处理客户端的连接,然后将处理客户端的IO流交给另一个线程。也就是我们常说的1+n关系。
(3)主从Reactor线程模型。这个其实就是启动一个线程池来监听客户端的连接,然后与客户端通信的IO流交给另一个线程处理。也就是我们所说的多对多关系。
那么,怎么在使用Netty搭建项目的时候配置这三种模式呢?接下来为你一一说明。
(1)单Reactor线程模型
我们可以跟进源码中看一下第三步引导配置过程。
从这一步可以看出,单Reactor线程模型是调用本类中的另一个group方法,其中的EventLoopGroup都是传递的上面创建的worker线程。
(2)多Reactor线程模式
我们知道,主从Reactor线程模型,是指一个线程进行监听并处理客户端的连接,拿到客户端的连接将其扔进另一个线程池中交给IO线程进行处理。
我们先看看怎么使用,如下所示。
与上面的区别在于,创建boss线程池的时候,传入参数1。这代表这个线程池只有一个线程,其实就是单线程。我们进入这个NioEventLoop源码中看一下。
其中,nThread参数为1,然后调用本类中的其他构造方法,所以用
this(nThreads,null);我们继续跟到这个构造函数中看一下。
跟到了这个方法,这个构造方法继续调用本类中的其他重载的构造方法。
我们继续跟进。
继续跟进。我们看到了熟悉的面孔。
我们看上面这个方法中,如果之前nThread参数设置为1,那么就采用我们定义的nThread进行创建线程池。
(3)主从Reactor线程模型
主从Reactor线程模型,其实就是采用一个线程组来处理监听和连接,另一个线程组来处理IO流。下面,让我们先来看看怎么使用。
和上面的多Reactor线程模型相比,其实就是创建boss线程池的时候,构造方法中采用的是无参构造函数。
NioEventLoopGroup无参构造函数默认没有传参数,会默认设置为0。
我们一步步跟到源码,和上面过程类似,最后进入这个函数。
如下图所示,我们看到,由于nThread这个参数为0,那么就会设置nThread为DEFAULT_EVENT_LOOP_THREADS。
而这个DEFAULT_EVENT_LOOP_THREADS参数的初始化是在这个静态代码块中,这个静态代码块先于这个类的构造方法执行。所以在执行构造函数的时候,这个DEFAULT_EVENT_LOOP_THREADS已经计算出来了。
DEFAULT_EVENT_LOOP_THREADS这个值就是调用Runtime中的getRuntime()这个static方法得到Runtime的实例对象,然后调用本类中的availableProcessors() 方法获取CPU核数。因此,上面创建的线程数默认为CPU的2倍。
注:availableProcessors() 方法是虚拟机中的native方法,调用操作系统底层API去获取了,有兴趣可以去看看注释说明。
题外话:为啥设置为CPU内核的两倍呢?因为根据高并发的理论,当线程数量为CPU的两倍,可以获得最高的运行效率。有兴趣的可以看看理论公式。
更多精彩内容请点击阅读:
《》
《》
《》
《》
《》
《》
《》
《》
以上是关于Netty中的常见问题的主要内容,如果未能解决你的问题,请参考以下文章
netty系列之:netty中的自动解码器ReplayingDecoder