学习Netty就不得不从TCP服务器和I/O模型说起,了解TCP服务器架构和I/O模型的演进有助于深入了解Netty。

TCP服务器的架构

一般地,TCP服务器有两种套接字,监听套接字和已连接套接字。监听套接字用于TCP的监听,一旦连接建立便产生已连接套接字,服务器利用已连接套接字与客户端进行通信。

  • 迭代服务器
  • 在迭代服务器中,监听套接字会一直阻塞直到能够接受连接,接受连接后利用已连接套接字与客户端通信,这些工作都是在同一个线程中完成的,示意Java代码如下。这种模式是串行处理,很难应对并发量较大的情况。
try (ServerSocket serverSocket = new ServerSocket(port)) { while (true) { Socket socket = serverSocket.accept(); // ... }} catch (IOException e) { e.printStackTrace();}
  • 并发服务器
  • 在并发服务器中,监听套接字会一直阻塞直到能够接受连接,接受连接后,服务器会让子线程/进程去处理已连接套接字,示意Java代码如下。这种模式虽然是并行处理,可以不干扰服务端的监听,但是由于每次新来一个请求就会产生一个新的线程去处理,出于资源的考虑很难应对高并发的情况。
try (ServerSocket serverSocket = new ServerSocket(port)) { while (true) { final Socket socket = serverSocket.accept(); new Thread(() -> { // ... }).start(); }} catch (IOException e) { e.printStackTrace();}
  • IO多路复用(事件驱动)
  • 为了能在一个线程中处理多个连接,可以使用IO多路复用(事件驱动),典型的有Linux C中的select、poll和epoll,Java的Selector类等。以Selector为例,调用者在选择器上为不同的连接注册自己感兴趣的事件(可读/可写/可接受/可连接),然后阻塞在select上,当事件发生时调用者便会得到通知,并且知道是哪个连接触发了事件,以便可以进一步处理。
  • Selector实现的HTTP服务器示意如下:
 public class NioServer { private static final int BUFFER_SIZE = 512; private static final String HTTP_RESPONSE_BODY = "Hello wolrd"; private static final String HTTP_RESPONSE_HEADER = "HTTP/1.1 200" + "Content-Type: text/html" + "Content-Length: " + HTTP_RESPONSE_BODY.length() + ""; private static final String HTTP_RESPONSE = HTTP_RESPONSE_HEADER + HTTP_RESPONSE_BODY;  // IO多路复用 public void selector(int port) { try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); Selector selector = Selector.open()) { serverSocketChannel.configureBlocking(false); serverSocketChannel.bind(new InetSocketAddress(port)); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); while (true) { int readyChannels = selector.select(); if (readyChannels == 0) { continue; } Set selectedKeys = selector.selectedKeys(); Iterator iter = selectedKeys.iterator(); while (iter.hasNext()) { SelectionKey key = iter.next(); if (key.isAcceptable()) { SocketChannel channel = ((ServerSocketChannel) key.channel()).accept(); System.out.println("accept: " + channel); channel.configureBlocking(false); channel.register(selector, SelectionKey.OP_READ); } if (key.isReadable()) { SocketChannel channel = (SocketChannel) key.channel(); System.out.println("read: " + channel); ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE); int bytesRead = channel.read(buffer); while (bytesRead > 0) { buffer.flip(); while (buffer.hasRemaining()) { System.out.print((char) buffer.get()); } buffer.clear(); bytesRead = channel.read(buffer); } ByteBuffer writeBuf = ByteBuffer.wrap(HTTP_RESPONSE.getBytes()); while (writeBuf.hasRemaining()) { channel.write(writeBuf); } channel.close(); } iter.remove(); } } } catch (IOException e) { e.printStackTrace(); } } }

I/O模型

一个输入操作通常包括两个不同的阶段[1][2]

  1. 等待数据准备好
  2. 从内核向进程复制数据

(1) 阻塞式I/O模型

(2) 非阻塞式I/O模型

(3) I/O复用模型

(4) 信号驱动式I/O模型

(5) 异步I/O模型

同步I/O和异步I/O对比

POSIX把这两个术语定义如下:

  • 同步I/O操作导致请求进程阻塞,直至I/O操作完成;
  • 异步I/O操作不导致请求进程阻塞。

根据上述定义,前4种模型——阻塞式I/O模型、非阻塞式I/O模型、I/O复用模型和信号驱动式I/O模型都是同步I/O模型,因为其中真正的I/O操作(recvfrom)将阻塞进程。只有异步I/O模型与POSIX定义的异步I/O相匹配。

Netty

Netty是一款异步的事件驱动的网络应用编程框架,支持快速地开发可维护的高性能的面向协议的服务器和客户端。与使用阻塞I/O来处理大量事件相比,使用非阻塞I/O来处理更快速、更经济,Netty使用了Reactor模式将业务和网络逻辑解耦,实现关注点分离[3]

Reactor模式

Reactor模式(反应堆模式)是一种处理一个或多个客户端并发交付服务请求的事件设计模式。当请求抵达后,服务处理程序使用I/O多路复用策略,然后同步地派发这些请求至相关的请求处理程序[4]

Reactor模式中的角色:

  • Reactor:监听端口,响应与分发事件;
  • Acceptor:当Accept事件到来时Reactor将Accept事件分发给Acceptor,Acceptor将已连接套接字的通道注册到Reactor上;
  • Handler:已连接套接字做业务处理。

单Reactor单线程

在这种模式中,Reactor、Acceptor和Handler都运行在一个线程中。

单Reactor多线程

在这种模式中,Reactor和Acceptor运行在同一个线程,而Handler只有在读和写阶段与Reactor和Acceptor运行在同一个线程,读写之间对数据的处理会被Reactor分发到线程池中。

多Reactor多线程

在这种模式中,主Reactor负责监听,与Acceptor运行在同一个线程,Acceptor会将已连接套接字的通道注册到从Reactor上,从Reactor负责响应和分发事件,起到类似多线程Reactor的作用。Netty服务端使用了该种模式。

reactor线程模型_从TCP服务器到I/O模型,带你学习Netty相关推荐

  1. java线程内存模型_深度解析Java多线程的内存模型

    内部java内存模型 硬件层面的内存模型 Java内存模型和硬件内存模型的联系 共享对象的可见性 资源竞速 Java内存模型很好的说明了JVM是如何在内存里工作的,JVM可以理解为java执行的一个操 ...

  2. python手势识别隐马尔可夫模型_使用隐马尔可夫模型的运动笔迹手势识别.doc

    您所在位置:网站首页 > 海量文档 &nbsp>&nbsp高等教育&nbsp>&nbsp科普读物 使用隐马尔可夫模型的运动笔迹手势识别.doc10页 ...

  3. tensorflow2 存取模型_思维导图:长短期记忆模型

    注:本文资料主要来自小能熊终生学习学院<千熊5月做到--21天费曼模型>,有兴趣的朋友可以查看「小能熊(candobear)」官网. 一.What | 什么是什么 [5月做到 费曼训练] ...

  4. 什么是非集计模型_集计与非集计模型的关系

    集计与非集计模型的关系 Wardrop 第一 . 第二平衡原理 集计模型 在 传统的交通规划或交通需求预测中,通常首先将对象地区或群体划分为若干个小区或群体等特 定的集合体,然后 以这些小区或群体为基 ...

  5. logit回归模型_你们要的二项Logit模型在这里——离散选择模型之八

    前言:本文主要介绍如何以效用最大化理论为基础,推导出二项 Logit(Binary Logit)模型. 本文为系列离散选择模型(Discrete Choice Model, DCM)系列文章的第8篇. ...

  6. 判刑形状模型_离散形状建模示规范表面模型.doc

    离散形状建模表示模型 如今,产品几何变在整个产品开发过程是企业竞争力的一个重要问题.在设计阶段,几何功能要求和公差都源自于设计意图.此外,制造和测试阶段是根据.GeoSpelling作为产品几何技术规 ...

  7. c调用python keras模型_使用TensorFlow 2.0创建Keras模型的三种方法

    TensorFlow 2.0和tf.keras提供了三种方式来实现神经网络模型:Sequential API Functional API Model subclassing 下面我将分别使用这三种方 ...

  8. Python标准库socketserver使用线程混入实现异步TCP服务器

    推荐图书: <Python程序设计开发宝典>,ISBN:978-7-302-47210-0,董付国,清华大学出版社 图书详情(京东): 董付国老师所有图书均提供配套教学资源. ====== ...

  9. java多线程 模型_一篇文章读懂Java多线程模型

    要真正了解Java的多线程,我们还要从进程和线程的概念说起 进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期 ...

最新文章

  1. 【点云论文速读】最佳点云分割分析
  2. 解密京东618大促数据库运维的攻守之道
  3. JS 总结之原型继承的几种方式
  4. emoji表情 与 iconfont 一锅炖
  5. 文件上怎么盖章_投标文件该怎么盖章呢?投标人必看!
  6. 图表可视化seaborn风格和调色盘
  7. 两个时间的差值Java,Java如何找到两个时间之间的差值?
  8. MATLAB Simulink中自定义函数和switch case的用法
  9. 【C语言】-一维数组
  10. Java实现文件及文件夹的删除
  11. 大数据导论章节答案_智慧树APP大数据导论第三单元章节测试答案
  12. Python之pip安装出现报错ERROR: Cannot unpack file
  13. 关于1931CIE——XYZ色坐标图转换到RGB色坐标关系
  14. AMCL代码详解(二)位姿初始化
  15. IE 获取不到元素 img标签层级默认变高
  16. 计算机win10分区软件,简单易用的win10分区软件:分区助手
  17. Zoning Houses Kattis 多组记录线段树/ST表
  18. 笔记本电脑合盖无法休眠,开盖黑屏
  19. 生活小妙方记录:治疗缠腰蛇
  20. java 雷霆战机 教程,java swing实现简单的雷霆战机小游戏项目源码附带视频指导修改教程...

热门文章

  1. POJ1988 Cube Stacking
  2. KEIL-MDK 5 CMSIS的问题
  3. 堆排序-Python
  4. web.py mysql_用Web.py 连接 MySQL 的时候怎么样连接远程数据库
  5. mysql物理优化_mysql物理优化器代价模型分析【原创】
  6. import导入工程时出现error:Description Resource Path Location Type Target runtime com.genuitec.runtime.gener
  7. C++ Primer 5th笔记(chap 18 大型程序工具)类型转换与多个基类
  8. 石墨烯区块链(1)系统架构
  9. 《研磨设计模式》chap25 访问者模式Visitor(3)联合组合模式+总结
  10. JavaWeb——内置对象session与httpSession对象是同一个东西么?