前言

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. In a Web Application and Mobile (hybrid), how to know which this platform running?

    needed depending on the platform to change the CSS to suit the size of the font. for example the DbG ...

  2. 记录quick cocos2d-x3.2升级至cocos2d-x3.8

    目前为止,quickcocos2d-x没有3.8版本,想用3.8又想用quick,所以只能自己升级了,自己先记录下,防止忘记. cocos2d-x3.8里面有quick framework,而simu ...

  3. HTML5学习笔记——1

    1.视频 <vedio src  controls  height width autoplay loop preload > </vedio> <source src ...

  4. 九 Django框架,Form表单验证

    表单提交 html <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  5. spring与mybati整合方法

    (1)spring配置文件: <!-- 引入jdbc配置文件 --> <context:property-placeholder location="jdbc.proper ...

  6. IO - 同步,异步,阻塞,非阻塞 (转帖:http://blog.csdn.net/historyasamirror/article/details/5778378)

    同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出 ...

  7. BEC listen and translation exercise 40

    However, recently there's been more and more interest in the development of ostrich farming in other ...

  8. Agc011_F Train Service Planning

    先放题面,再放LHX巨佬题解 接着就是%%%.$orz.Oro.Or2.Otz.OTL.sto.rzo.Jto$.On_.○| ̄|_啊 模拟赛里直接把这道题刚掉了 一题升天·爆踩全场 这题思维跨越度已 ...

  9. YNOI2016 这是我自己的发明

    看到这个标题立刻想到:. “绝地科学家,八倍不屏息啊,八百里外把头打啊...” 首先我们发现如果只考虑第二个操作,这棵树就是假的,我们可以直接莫队解决 如果考虑换根的话...可以把一个操作换成小于等于 ...

  10. luogu1353 Running

    dp[i][j]表示走i分钟疲劳值为j时的最远距离 然后搞一下就好啦 #include <iostream> #include <cstdio> #include <al ...