谈谈Netty的线程模型

一、前言

Netty是一个异步、基于事件驱动的网络应用程序框架,其对 Java NIO进行了封装,大大简化了 TCP 或者 UDP 服务器的网络编程。其应用还是比较广泛的,比如Apache Dubbo 、Apache RocketMq、Zuul 2.0服务网关、Spring WebFlux、Sofa-Bolt 底层网络通讯都是基于 Netty 来实现的,本节我们谈谈Netty4中的线程模型。

二、 Netty的线程模型

image.png

如上图下侧为Netty Server端,当NettyServer启动时候会创建两个NioEventLoopGroup线程池组,其中boss组用来接受客户端发来的连接,worker组则负责对完成TCP三次握手的连接进行处理;如上图每个NioEventLoopGroup里面包含了多个NioEventLoop,每个NioEventLoop中包含了一个NIO Selector、一个队列、一个线程;其中线程用来做轮询注册到Selector上的Channel的读写事件和对投递到队列里面的事件进行处理。

当NettyServer启动时候会注册监听套接字通道NioServerSocketChannel到boss线程池组中的某一个NioEventLoop管理的Selector上,然后其对应的线程则会负责轮询该监听套接字上的连接请求;当客户端发来一个连接请求时候,boss线程池组中注册了监听套接字的NioEventLoop中的Selector会读取读取完成了TCP三次握手的请求,然后创建对应的连接套接字通道NioSocketChannel,然后把其注册到worker线程池组中的某一个NioEventLoop中管理的一个NIO Selector上,然后该连接套接字通道NioSocketChannel上的所有读写事件都由该NioEventLoop管理。当客户端发来多个连接时候,NettyServer端则会创建多个NioSocketChannel,而worker线程池组中的NioEventLoop是有个数限制的,所以Netty有一定的策略把很多NioSocketChannel注册到不同的NioEventLoop上,也就是每个NioEventLoop中会管理好多客户端发来的连接,然后通过循环轮询处理每个连接的读写事件。

如上图上侧部分为Netty Client部分,当NettyClient启动时候会创建一个NioEventLoopGroup,用来发起请求并对建立TCP三次连接的套接字的读写事件进行处理。当调用Bootstrap的connect方法发起连接请求后内部会创建一个NioSocketChannel用来代表该请求,并且会把该NioSocketChannel注册到NioSocketChannel管理的某个NioEventLoop的Selector上,然后该NioEventLoop的读写事件都有该NioEventLoop负责处理。

Netty之所以说是异步非阻塞网络框架是因为通过NioSocketChannel的write系列方法向连接里面写入数据时候是非阻塞的,马上会返回的,即使调用写入的线程是我们的业务线程,这是Netty通过在ChannelPipeline中判断调用NioSocketChannel的write的调用线程是不是其对应的NioEventLoop中的线程来实现的,如果发现不是则会把写入请求封装为WriteTask投递到其对应的NioEventLoop中的队列里面,然后等其对应的NioEventLoop中的线程轮询连接套接字的读写事件时候捎带从队列里面取出来执行;总结说就是每个NioSocketChannel对应的读写事件都是在其对应的NioEventLoop管理的单线程内执行,对同一个NioSocketChannel不存在并发读写,所以无需加锁处理。

另外当从NioSocketChannel中读取数据时候,并不是使用业务线程来阻塞等待,而是等NioEventLoop中的IO轮询线程发现Selector上有数据就绪时候,通过事件通知方式来通知我们业务数据已经就绪,可以来读取并处理了。

总结一句话就是使用Netty框架进行网络通信时候,当我们发起请求后请求会马上返回,而不会阻塞我们的业务调用线程;如果我们想要获取请求的响应结果,也不需要业务调用线程使用阻塞的方式来等待,而是当响应结果出来时候使用IO线程异步通知业务的方式,可知在整个请求-响应过程中业务线程不会由于阻塞等待而不能干其他事情。

下面我们讨论两个细节,第一是完成TCP三次握手的套接字应该注册到worker线程池中的哪一个NioEventLoop的Selector上,第二个是NioEventLoop中的线程负责监听注册到Selector上的所有连接的读写事件和处理队列里面的消息,那么会不会导致由于处理队列里面任务耗时太长导致来不及处理连接的读写事件?

对于第一个问题NioEventLoop的分配,Netty默认使用的是PowerOfTwoEventExecutorChooser,其代码如下:

    private final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser {
        @Override
        public EventExecutor next() {
            return children[childIndex.getAndIncrement() & children.length - 1];
        }
    }

可知是采用的轮询取模方式来进行分配。

对于第二个问题,Netty默认是采用时间均分策略来避免某一方处于饥饿状态:

  
//1.记录开始处理时间
final long ioStartTime = System.nanoTime();
try {//1.1处理连接套接字的读写事件
    processSelectedKeys();
} finally {
    // 1.2计算连接套接字处理耗时,ioRatio默认为50
    final long ioTime = System.nanoTime() - ioStartTime;
    //1.3运行队列里面任务
    runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
}               

如上代码1.1处理所有注册到当前NioEventLoop的Selector上的所有连接套接字的读写事件,代码1.2用来统计其耗时,由于默认情况下ioRatio为50,所以代码1.3尝试使用与代码1.2执行相同的时间来运行队列里面的任务。
也就是处理套接字读写事件与运行队列里面任务是使用时间片轮转方式轮询执行。

三、总结

Netty的异步非阻塞基于事件驱动的模型大大简化了我们编写网络应用程序的成本。

file
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容