前言

Netty 的线程模型是基于NIO的Selector 构建的,使用了异步驱动的Reactor 模式来构建的线程模型,可以很好的支持成百上千的 SocketChannel 连接。由于 READ/WRITE 都是非阻塞的,可以充分提升I/O线程的运行效率 ,避免了IO阻塞导致线程挂起, 同时可以让一个线程支持对多个客户端的连接SocketChannel的 READ/WRITE 操作, 从根本上解决了传统阻塞IO的一线程处理一连接的弊端。

高效率的Reactor模式

Reactor 模式

是一种为处理服务请求并发,提交到一个或者多个服务处理程序的事件设计模式。当请求抵达后,服务处理程序使用解多路分配策略,然后同步地派发这些请求至相关的请求处理程序
(来自维基百科:https://zh.wikipedia.org/wiki/反应器模式)

常见的reactor模式有以下三种

  1. 单线程reactor
  2. 多线程reactor
  3. 主从reactor

1、单线程reactor

ractor 单线程模式是指所有的I/O操作都在一个NIO线程完成,该线程的职责:

1.作为NIO服务端,接收客户端TCP连接

2.作为NIO客户端,向客户端发送TCP连接

3.READ/WRITE 客户端的请求

不过单线程的reactor 模式无法发挥多核的优势,因此对于高并发量的系统仍然存在瓶颈,主要原因如下:

1、reactor 线程既要处理来自客户端的连接,又要处理READ/WRITE/编码/解码。即便cpu 100% 也难以满足实际场景的需求

多线程Reactor 解决了这些问题

2、多线程reactor模型

reactor 多线程的实现最大的区别是拥有一个专门用来处理实际I/O 操作是线程池

优点:

1、拥有一个Acceptor 专门用来监听请求的I/O 类型

2、使用专门线程池可以提高acceptor的并发量,并且可以将同一个SocketChannel 放于同一个I/O 线程处理,同一个I/O线程可以处理多个SocketChannel的READ/WRITE事件

在大部分场景,该线程模型都能处理,但存在这样一种场景:单个Acceptor 线程 可能会因为需要监听大量的 SocketChannel 连接 或 I/O事件处理或在建立建立时需要进行安全的握手认证、黑白名单过滤,而导致出现性能瓶颈。所以这种场景下,单独一个Accceptor 会导致性能不足,便出现了第三种线程模型,主从Reactor 模型

3、主从reactor 多线程模型

相比多线程reactor模型,主从reactor多线程模型拥有了一个独立处理 SocketChannel 连接的线程池,当客户端从Acceptor建立连接之后,便将该连接绑定到subreactor 线程池中的某个线程中,然后由该线程绑定客户端感兴趣的I/O事件(READ/WRITE),监听客户端连接请求,最后处理。

mainReactor : 监听 ServerSocketChannel 、建立与 SocketChannel  的连接、将完成建立连接之后的Socket 交给subReactor

subReactor : 监听SocketChannel的 I/O事件,完成编解码、相应的业务处理(默认为CPU个数)

Netty的线程模型可以通过配置不同参数实现不同reactor的线程模型(netty4版本未发现多线程reactor版本实现方式)

1、单线程reactor

NioEventLoopGroup loopGroup = new NioEventLoopGroup(1);
ServerBootstrap b = new ServerBootstrap();
b.group(loopGroup, loopGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.DEBUG))
.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
// xxx
}
});
try {
ChannelFuture future = b.bind(8086).sync();
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
loopGroup.shutdownGracefully().sync();
}

2、主从reactor

NioEventLoopGroup mainGroup = new NioEventLoopGroup(1);
NioEventLoopGroup subGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors());
ServerBootstrap b = new ServerBootstrap();
b.group(mainGroup, subGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.DEBUG))
.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
// xxx
}
}); try {
ChannelFuture future = b.bind(8086).sync();
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
mainGroup.shutdownGracefully().sync();
subGroup.shutdownGracefully().sync();
}

NioEventLoop 与 NioEventLoopGroup 介绍

1、NioEventLoopGroup 是通过实现JUC 包相关线程池的接口来达到自定义线程池的目的,而NioEventLoop 则持有一个线程,用来处理SocketChannel 建立连接之后的I/O事件。

2、在初始化 NioEventLoopGroup 时,将初始化一定数量 NioEventLoop,并将这些初始化之后的 NioEventLoops 的引用交给NioEventLoopGroup 管理

3、由接口的实现可以看出,他们都是实现了juc 线程池的顶层接口  Executor,因此都具有公共的 execute(Runable command)及 submit(Runable task) 方法,那么这些通用的方法将为 NioEventLoopGroup  把任务交给 子的NioEventLoop处理提供标准及便利

//轮询一个子的 NioEventLoop 进行提交处理
@Override
public Future<?> submit(Runnable task) {
return next().submit(task);
}
......
@Override
public void execute(Runnable command) {
next().execute(command);
}

Netty 具体线程模

从整个线程模型来看 相关组件之间的是如何相互协作的

 

1、初始化NioEventLoopGroup ,  将为ServerSocketChannel 提供一个 bossGroup 线程池,为 SockerChannel 的I/O 事件处理 提供一个workGroup

2、使用ServerBootstrap 绑定端口等相关信息,此时会初始化一个ServerSocketChannel 和 bossGroup,并且将 ServerSocketChannel 绑定到 bossGroup 中的一个NioEventLoop 中进行监听客户端的连接请求

3、当 Client 发起连接请求时,首先经过三次握手通过后,然后服务端被触发,接着收到连接成功的通知(因为是异步所以是触发)

4、ServerSocketChannel 收到连接成功的通知后,将建立好的连接交给 workGroup中的某个NioEventLoop,然后将感兴趣的事件注册到 该 NioEventLoop 持有的Selector上,等待Client 下一次请求

5、当 Client 发起 READ/WRITE 相关的请求时,则提交给NioEventLoop  进行处理

 

参考:

http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf

 

Netty 线程模型与Reactor 模式的更多相关文章

  1. Java后端进阶-网络编程(Netty线程模型)

    前言 我们在使用Netty进行服务端开发的时候,一般来说会定义两个NioEventLoopGroup线程池,一个"bossGroup"线程池去负责处理客户端连接,一个"w ...

  2. Netty — 线程模型

    一.前言 众所周知,netty是高性能的原因源于其使用的是NIO,但是这只是其中一方面原因,其IO模型上决定的.另一方面源于其线程模型的设计,良好的线程模型设计,能够减少线程上下文切换,减少甚至避免锁 ...

  3. eventloop & actor模式 & Java线程模型演进 & Netty线程模型 总结

    eventloop的基本概念可以参考:http://www.ruanyifeng.com/blog/2013/10/event_loop.html Eventloop指的是独立于主线程的一条线程,专门 ...

  4. Netty线程模型

    一.Reactor模型 1.单线程模型 Reactor单线程模型,指的是所有的IO操作都在同一个NIO线程上面完成,NIO线程的职责如下: 1)作为NIO服务端,接收客户端的TCP连接: 2)作为NI ...

  5. Netty系列之Netty线程模型

    Reference: http://www.infoq.com/cn/articles/netty-threading-model 1. 背景 1.1. Java线程模型的演进 1.1.1. 单线程 ...

  6. 彻底搞懂 netty 线程模型

    编者注:Netty是Java领域有名的开源网络库,特点是高性能和高扩展性,因此很多流行的框架都是基于它来构建的,比如我们熟知的Dubbo.Rocketmq.Hadoop等.本文就netty线程模型展开 ...

  7. Netty 线程模型

    一.线程模型概述 线程模型表明了代码的执行方式.从最开始的使用单线程,后来出现了多线程,之后是线程池.当有要执行的任务时,任务会被传到线程池,从线程池中获得空闲的线程来执行任务,执行完了后会将线程返回 ...

  8. Netty源码死磕一(netty线程模型及EventLoop机制)

    引言 好久没有写博客了,近期准备把Netty源码啃一遍.在这之前本想直接看源码,但是看到后面发现其实效率不高, 有些概念还是有必要回头再细啃的,特别是其线程模型以及EventLoop的概念. 当然在开 ...

  9. Reactor三种线程模型与Netty线程模型

    文中所讲基本都是以非阻塞IO.异步IO为基础.对于阻塞式IO,下面的编程模型几乎都不适用 Reactor三种线程模型 单线程模型 单个线程以非阻塞IO或事件IO处理所有IO事件,包括连接.读.写.异常 ...

随机推荐

  1. 多种方法求java求整数的位数

    方法一 private static int getNumLenght(long num){ num = num>0?num:-num; return String.valueOf(num).l ...

  2. Docker-使用Dockerfile创建镜像

    Dockerfile是一个文本格式的配置文件,用户可以使用Docker来快速创建自定义的镜像 基本结构 Dockerfile由一行行命令语句组成,并且支持以#开头的注释行 一般而言,Dockerfil ...

  3. 使用 sqoop 将mysql数据导入到hive表(import)

    Sqoop将mysql数据导入到hive表中 先在mysql创建表 CREATE TABLE `sqoop_test` ( `id` ) DEFAULT NULL, `name` varchar() ...

  4. HDU 4417 Super Mario(2012杭州网络赛 H 离线线段树)

    突然想到的节约时间的方法,感觉6翻了  给你n个数字,接着m个询问.每次问你一段区间内不大于某个数字(不一定是给你的数字)的个数 直接线段树没法做,因为每次给你的数字不一样,父节点无法统计.但是离线一 ...

  5. 初步认识Express框架渲染视图

    给出一个简单的例子,讲述模板渲染的基础功能 在nodejs中使用express框架,默认的是ejs和jade渲染模板,以下是以ejs模板进行解析 1.ejs 模板安装 npm install ejs ...

  6. OpenCV——百叶窗

    参考: PS 图像特效,百叶窗 // define head function #ifndef PS_ALGORITHM_H_INCLUDED #define PS_ALGORITHM_H_INCLU ...

  7. 【leetcode刷题笔记】Remove Duplicates from Sorted Array II

    Follow up for "Remove Duplicates":What if duplicates are allowed at most twice? For exampl ...

  8. 系列文章--AJAX技术系列总结

    各种AJAX方法的使用比较 用ASP.NET写个SQLSERVER的小工具  写自己的ASP.NET MVC框架(下)  写自己的ASP.NET MVC框架(上)  用Asp.net写自己的服务框架  ...

  9. 白话算法(6) 散列表(Hash Table)从理论到实用(中)

    不用链接法,还有别的方法能处理碰撞吗?扪心自问,我不敢问这个问题.链接法如此的自然.直接,以至于我不敢相信还有别的(甚至是更好的)方法.推动科技进步的人,永远是那些敢于问出比外行更天真.更外行的问题, ...

  10. NB-IoT知识

    通常,我们把物联网设备分为三类: ①无需移动性,大数据量(上行),需较宽频段,比如城市监控摄像头. ②移动性强,需执行频繁切换,小数据量,比如车队追踪管理. ③无需移动性,小数据量,对时延不敏感,比如 ...