IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 初识Netty(一) -> 正文阅读

[网络协议]初识Netty(一)

????????扑街前言:上篇文章说了I/O,那都是为了这个做铺垫netty才是重点,学习这个人都麻了,不知道说什么前言了,就这样吧!(认识到自己是菜鸟的不知道多少天)


Netty的概述

????????Netty是由JBOSS提供的一个Java开源框架,现为Github上的独立项目。Netty提供非阻塞的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。

  • 本质:网络应用程序框架;
  • 实现:异步、事件驱动;
  • 特性:高性能、可维护、快速开发;
  • 用途:开发服务器和客户端。

Netty的核心架构

  • 核心:可扩展的事件模型;统一的通信api,简化了通信编码;零拷贝机制与丰富的字节缓冲区。
  • 传输服务:支持socket以及datagram(数据报);http传输服务;In-VM Pipe(管道协议,是jvm的一种进程)。
  • 协议支持:http以及websocket;SSL安全套接字协助支持;Google Protobuf(序列化框架);支持zlib、gzip压缩;支持大文件的传输;RTSP(实时流传输协议,是TCP/IP协议体系中的一个应用层协议);支持二进制协议并且提供了完整的单元测试。


开发网络应用不选JDK原生API 而选Netty的理由

API:

????????Netty更友好更强大:1、JDK中NIO的一些API功能薄弱且复杂,Netty隔离了JDK中NIO的实现变化及实现细节譬如:ByteBuffer -> ByteBuf主要负责从底层的IO中读取数据到ByteBuf,然后传递给应用程序,应用程序处理完之后封装为ByteBuf,写回给IO。

并发编程:

????????Netty自身线程安全:使用JDK原生API需要对多线程要很熟悉, 因为N I O 涉及到Reactor设计模式,得对里面的原理要相当的熟悉。

高可用:

????????完整的高可用机制:JDK原生方式要实现高可用,需要自己实现断路重连、半包读写、粘包处理、失败缓存处理等相关操作,而Netty则做的更多,它解决了传输的一些问题譬如粘包半包现象,它支持常用的应用层协议,完善的断路重连,idle等异常处理。

Bug:

????????JDK NIO BUG:JDK的NIO存在bug,如经典的epoll bug,会导致CPU 100%而Netty封装的更完善。


Netty对三种IO的支持

? ? ? ? 上篇文章我们已经说过了三种IO的基本概念,目前我们再了解一下Netty对三种IO的支持,如下截图。


Reactor 线程模型

? ? ? ? Reactor线程模型不是Java的专属,也不是Netty专属,它其实是一种并发编程模型,是一种思想,具有指导意义。

Reactor模型中定义了三种角色:

  • Reactor:负责监听和分配事件,将I/O事件分派给对应的Handler。新的时间包含连接建立就绪、读就绪、写就绪等。
  • Acceptor:处理客户端新连接,并分派请求到处理器链中。
  • Handler:将自身与事件绑定,执行费阻塞读/写人物,完成channel的读入,完成处理业务逻辑后,负责将结果写出channel。

单Reactor - 单线程模型

? ? ? ? NIO下Reactor单线程,所有的接受连接,处理数据的相关操作都在一个线程中完成,性能上有瓶颈。可以参考上面文章实现的NIO服务。

单Reactor - 多线程模型

? ? ? ? 把比较消耗时的数据的编解码运算操作放入线程池中执行,虽然提升了性能但是还不是最好的方式。

主从Reactor - 多线程

? ? ? ? 主从多线程,对于服务器来说,接收客户端的连接是比较重要的,因此将这部分操作单独用线程去操作。

?主从Reactor工作模式

? ? ?这种模式的基本工作流程为:

  1. Reactor主线程MainReactor对象通过select监听客户端连接事件,收到事件后,通过Acceptor处理客户端连接事件。
  2. 当Acceptor处理完客户端连接事件之后(与客户端建立号socket连接),MainReactor将连接分配给subReactor。(即:MainReactor只负责监听客户端的请求,和客户端建立连接后将连接交给subReactor监听后面的IO事件。)
  3. subReactor将连接加入到自己的连接队列进行监听,并创建Handler对各种事件进行处理。
  4. 当连接上有新事件发生的时候,subReactor将会调用对应的Handler处理。
  5. Handler通过read从连接上读取请求数据,将请求数据分发给Worker线程池进行业务处理。
  6. worker线程池会分配独立的线程来完成真正的业务处理,并将处理结果返回给handler。Handler通过send向客户端发送响应数据。
  7. 一个MainReactor可以对应多个subReactor,即一个MainReactor线程可以对应多个subReactor线程。

主从Reactor优势

? ? ?这种模式的优势如下:

  1. MainReactor 线程与SubReactor 线程的数据交互简单职责明确,MainReactor 线程只需要接受新连接,SubReactor 线程完成后续的业务处理。
  2. MainReactor 线程与SubReactor 线程的数据交互简单,MainReactor 线程只需要把新连接传给SubReactor 线程,SubReactor 线程无需返回数据。
  3. 多个SubReactor 线程能够应对更高的并发请求。

? ? ?这种模式的缺点是编程复杂度高。但是由于优点明显,在许多项目中被广泛使用,包括Nginx、Memcachend、Netty等。

? ? ?这种模式也被叫做服务器的 1+M+N线程模式,即使用改模式开发的服务器包含一个(或多个,1只是表示相对较少)连接建立线程 + M 个IO 线程 + N 个业务处理线程。这是业界成熟的服务器程序设计模式。


Netty中的Reactor实现

  1. Netty抽象出两组线程池:Boss EventLoopGroup和Worker EventLoopGroup,每个线程池中都有 EventLoopGroup 线程(可以是OIO,NIO,AIO)。Boss EventLoopGroup中的线程专门负责处理和客户端建立连接,Worker EventLoopGroup 中的线程专门负责处理连接上的读写,EventLoopGroup 相当于一个事件循环组,这个组中含有锁多个事件循环。
  2. EventLoop 表示一个不断循环的执行事件处理的线程,每个EventLoop 都含有一个selector,用于监听注册在其上的socket 网络连接(channel)。
  3. 每一个Boss EventLoopGroup 中循环执行以下三个步骤:a、select:轮询注册在其上的serverSocketChannel 的 accept 事件(OP_ACCEPT 事件);b、processSeleckendKeys:处理 accept 事件,与客户端建立连接,生产一个socketChannel,并将其注册到Worker EventLoop 上的某个selector 上;c、runAllTasks:再去以此循环处理任务队列中的其他任务。
  4. 每个Worker EventLoop 中循环执行这三个步骤:a、select:轮询注册在其上的socketChannel 的read / write 事件(OP_READ / OP_WRITE 事件);b、processSeleckendKeys:在对应的socketChannel 上处理read / write 事件;c、runAllTasks:再去以此循环处理任务队列中的其他任务。
  5. 在以上两个processSeleckendKeys步骤中,会使用Pipeline(管道),Pipeline 中引用了channel,即通过Pipeline 可以获取对应的Channel,Pipeline 中维护了很多的处理器(拦截处理器、过滤处理器、自定义处理器等)。

?Netty 线程模型其他事项

  1. Netty 的线程模型基于主从多Reactor模型。通常由一个线程负责处理OP_ACCEPT事件,拥有 CPU 核数的两倍的IO线程处理读写事件;
  2. 一个通道的IO操作会绑定在一个IO线程中,而一个IO线程可以注册多个通道;
  3. 在一个网络通信中通常会包含网络数据读写,编码、解码、业务处理。默认情况下网络数据读写,编码、解码等操作会在IO线程中运行,但也可以指定其他线程池;
  4. 通常业务处理会单独开启业务线程池(看业务类型),但也可以进一步细化,例如心跳包可以直接在IO线程中处理,而需要再转发给业务线程池,避免线程切换;
  5. 在一个IO线程中所有通道的事件是串行处理的;
  6. 通常业务操作会专门开辟一个线程池,那业务处理完成之后,如何将响应结果通过 IO 线程写入到网卡中呢?业务线程调用 Channel对象的 write 方法并不会立即写入网络,只是将数据放入一个待写入缓存区,然后IO线程每次执行事件选择后,会从待写入缓存区中获取写入任务,将数据真正写入到网络中。

Pipeline中的ChannelPipeline & ChannelHandler

????????处理器ChannelHandler:ChannelPipeline 提供了 ChannelHandler 链的容器。以服务端程序为例,客户端发送过来的数据要接收,读取处理,我们称数据是入站的,需要经过一系列Handler处理后;如果服务器想向客户端写回数据,也需要经过一系列Handler处理,我们称数据是出站的。ChannelPipeline 和 ChannelHandler 之间是相互绑定的,也就是一对一关系。

ChannelHandler 分类

????????inbound/outbound:对于数据的出站和入站,有着不同的ChannelHandler类型与之对应:ChannelInboundHandler 入站事件处理器、ChannelOutBoundHandler 出站事件处理器、ChannelHandlerAdapter提供了一些方法的默认实现,可减少用户对于ChannelHandler的编写、ChannelDuplexHandler:混合型,既能处理入站事件又能处理出站事件。从下面的关系图可以看出,如果我们需要自己的Handler的时候,读取事件可以继承ChannelInboundHandlerAbapter,写出事件可以继承ChannelOutBoundHandlerAbapter。

?ChannelHandler 体系结构

????????inbound/outbound:inbound入站事件处理顺序(方向)是由链表的头到链表尾,outbound事件的处理顺序是由链表尾到链表头。inbound入站事件由netty内部触发,最终由netty外部的代码消费。outbound事件由netty外部的代码触发,最终由netty内部消费。


? ? ? ? 上述就对netty的一些简单说明,后续还有netty的核心组件剖析等一些的内容,本次就说这些。?

?

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-01-08 14:25:09  更:2022-01-08 14:26:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 11:31:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码