【Netty 一】

news2024/9/20 16:52:23

Netty是什么

Netty 是一个高性能、异步事件驱动的 NIO 框架,基于 JAVA NIO 提供的 API 实现。它提供了对
TCP、 UDP 和文件传输的支持,作为一个异步 NIO 框架, Netty 的所有 IO 操作都是异步非阻塞
的, 通过 Future-Listener 机制,用户可以方便的主动获取或者通过通知机制获得 IO 操作结果。
在这里插入图片描述

Netty 高性能

多路复用通讯方式

  • Selector:
    在 Java NIO 中,Selector 是一个多路复用器,它允许单个线程同时管理多个通道的 I/O 操作。Netty 内部使用 Selector 实现多路复用。

异步通信NIO

Netty 的异步通信通过以下几个方面实现:

  • 非阻塞 I/O: Netty 使用非阻塞 I/O 操作,确保 I/O 操作不会阻塞线程。这意味着在执行 I/O 操作时,线程可以继续处理其他任务,而不是被阻塞。
  • 事件驱动: Netty 是事件驱动的框架,通过事件循环模型(Reactor 模式)来处理 I/O 事件。事件处理是异步的,事件会被分发到相应的处理器进行处理。
  • 回调机制: Netty 提供了回调机制,通过异步的 API 调用来处理 I/O 操作的结果,避免了同步等待的开销。

零拷贝

  1. Netty 的接收和发送 ByteBuffer 采用 DIRECT BUFFERS,使用堆外直接内存进行 Socket 读写,
    不需要进行字节缓冲区的二次拷贝。如果使用传统的堆内存(HEAP BUFFERS)进行 Socket 读写,
    JVM 会将堆内存 Buffer 拷贝一份到直接内存中,然后才写入 Socket 中。相比于堆外直接内存,
    消息在发送过程中多了一次缓冲区的内存拷贝。
  2. Netty 提供了组合 Buffer 对象,可以聚合多个 ByteBuffer 对象,用户可以像操作一个 Buffer 那样
    方便的对组合 Buffer 进行操作,避免了传统通过内存拷贝的方式将几个小 Buffer 合并成一个大的
    Buffer。
  3. Netty的文件传输采用了transferTo方法,它可以直接将文件缓冲区的数据发送到目标Channel,
    避免了传统通过循环 write 方式导致的内存拷贝问题

内存池

随着 JVM 虚拟机和 JIT 即时编译技术的发展,对象的分配和回收是个非常轻量级的工作。但是对于缓
冲区 Buffer,情况却稍有不同,特别是对于堆外直接内存的分配和回收,是一件耗时的操作。为了尽
量重用缓冲区, Netty 提供了基于内存池的缓冲

Reactor线程模型

Reactor 单线程模型

在这里插入图片描述

Reactor 单线程模型 是最简单的 Reactor 模式实现,它在单个线程中处理所有的 I/O 事件。该模型通常适用于负载较低、事件处理逻辑简单的场景。

工作原理

  • 事件循环: 在单线程中运行 Reactor 实例,这个线程负责监听 I/O 事件,并将这些事件分发给相应的事件处理器。
  • 单线程处理: 所有的 I/O 事件(如读、写、连接等)都由单个线程处理,线程通过 Selector 监听事件并调用注册的处理程序。

优点

  • 简单: 实现简单,易于理解和维护。
  • 避免线程切换: 由于只有一个线程,所以没有线程切换的开销。

缺点

  • 可扩展性差: 由于所有事件都在一个线程中处理,这可能导致性能瓶颈,尤其是在高负载的情况下。
  • 单点故障: 如果处理逻辑中的某个操作阻塞,会影响整个线程的性能。

适用场景

  • 低负载、事件处理简单的应用场景。
Reactor 多线程模型

在这里插入图片描述

Reactor 多线程模型 使用多个线程来处理 I/O 事件,这种模型通过将处理逻辑分散到多个线程中,提高了系统的并发处理能力。

工作原理

  • 多线程 Reactor: 在多线程模型中,Reactor 实例使用多个线程来处理 I/O 事件。每个线程都有一个 EventLoop,负责处理事件并将这些事件分发给对应的 ChannelHandler。
  • 事件分发: 事件通过多个 Reactor 实例(线程)进行处理,每个线程可能处理不同的 Channel 或者不同的 I/O 操作。

优点

  • 高性能: 多线程可以提高并发处理能力,适用于高负载的应用场景。
  • 响应更快: 分散到多个线程中处理事件,可以避免单线程的瓶颈,提高系统的整体响应速度。

缺点

  • 复杂性增加: 实现和维护更加复杂,需要处理线程间的同步和协调。
  • 线程开销: 线程的创建和上下文切换会带来一定的开销。、

适用场景

  • 中高负载的应用场景,尤其是需要处理大量并发连接和高并发请求的场景。
Reactor 主从多线程模型

在这里插入图片描述
Reactor 主从多线程模型 是一种更为复杂和灵活的实现方式,结合了主线程和从线程的优势,以处理高并发的网络 I/O。

工作原理

  • 主线程(Boss Thread): 主线程负责监听新的连接请求。它接收新的连接并将其注册到从线程池中的 EventLoop 中进行处理。
  • 从线程(Worker Threads): 从线程池负责处理已经接受的连接的 I/O 操作(如读、写)。每个从线程处理一部分连接的事件,通常通过 Selector 来监听 I/O 事件。

优点

  • 高效的连接管理: 主线程负责接受连接和管理连接的生命周期,而从线程专注于处理 I/O 操作,提高了连接的处理效率。
  • 负载均衡: 通过将连接的 I/O 操作分散到多个从线程中,可以平衡负载,避免单线程处理过多的连接。

缺点

  • 实现复杂: 需要合理设计和实现主线程和从线程的协调机制。
  • 线程切换开销: 可能存在一定的线程切换开销,但通常比单线程模型要小。

适用场景

  • 高负载、高并发的应用场景,尤其适合需要处理大量连接和高并发请求的场景。

序列化框架

Netty 默认提供了对 Google Protobuf 的支持,通过扩展 Netty 的编解码接口,用户可以实现其它的高性能序列化框架,例如 Thrift 的压缩二进制编解码框架

序列化(Serialization)

序列化 是将对象转化为字节流的过程,这样对象就可以被存储到磁盘或者通过网络传输到其他系统。序列化的目的是将对象的状态保存下来,以便在需要时恢复。一般也将序列化称为编码,主要用于网络传输、数据持久化等;

反序列化(Deserialization)

反序列化 是将字节流转换回对象的过程。它的目的是将之前序列化保存的数据恢复成原始的对象,以便进行进一步的处理。一般也将反序列化称为解码(Decode),主要用于网络传输对象的解码,以便完成远程调用。

框架

Java 原生序列化
缺点:

  • 无法跨语言:我认为这对于Java序列化的发展是致命的“失误”,因为Java序列化后的字节数组,其它语言无法进行反序列化。

  • 序列化后的码流太大:相对于目前主流的序列化协议,Java序列化后的码流太大;

JSON
SON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。它基于 ECMAScript (w3c制定的js规范)的一个子集, JSON采用与编程语言无关的文本格式,但是也使用了类C语言(包括C, C++, C#, Java, JavaScript, Perl, Python等)的习惯,简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。

  • 优点

    • 前后兼容性高
    • 数据格式比较简单,易于读写
    • 序列化后数据较小,可扩展性好,兼容性好
    • 与XML相比,其协议比较简单,解析速度比较快
  • 缺点

    • 数据的描述性比XML差
    • 不适合性能要求为ms级别的情况
    • 额外空间开销比较大

Protobuf

  • 优点:

    • 高效:Protobuf 使用紧凑的二进制格式,序列化和反序列化速度快,数据量小。
    • 跨语言支持:支持多种编程语言,如 Java、C++、Python、Go 等。
    • 易于维护:有明确的 schema 定义,支持向前和向后兼容的字段修改。
  • 缺点:

    • 学习曲线:需要定义 .proto 文件,并使用工具生成代码,可能需要一些学习时间。
    • 缺乏自描述性:生成的二进制数据不包含字段名称等信息,解析时需要依赖 schema。
  • 使用场景:

    • 高性能应用:需要高效的数据传输和存储。
    • 跨语言通信:在不同编程语言之间进行数据交换。
    • 复杂数据模型:数据结构复杂,需要定义清晰的 schema。

Thrift

  • 优点:

    • 多语言支持:支持多种编程语言,包括 Java、C++、Python、PHP、Go 等。
    • 灵活性:支持多种传输协议和序列化格式,如二进制、JSON 等。
    • RPC 支持:内置 RPC 框架,方便进行远程调用。
  • 缺点:

    • 复杂性:有较多的配置选项和复杂的环境依赖。
    • 性能:在某些情况下,性能可能不如 Protobuf 和 Avro。
  • 使用场景:

    • 分布式系统:需要支持远程过程调用(RPC)和服务定义。
    • 跨语言系统:在多个语言中实现数据交换和服务调用。
    • 协议选择:需要根据具体需求选择不同的传输协议和序列化格式。

Avro

  • 定义:
    Avro属于Apache Hadoop的一个子项目。 Avro提供两种序列化格式:JSON格式或者Binary格式。Binary格式在空间开销和解析性能方面可以和Protobuf媲美,Avro的产生解决了JSON的冗长和没有IDL的问题

  • 优点

    • 支持丰富的数据类型
    • 简单的动态语言结合功能
    • 具有自我描述属性
    • 提高了数据解析速度
    • 快速可压缩的二进制数据形式
    • 可以实现远程过程调用RPC
    • 支持跨编程语言实现
  • 缺点

    • 对于习惯于静态类型语言的用户不直观
  • 适用场景

    • 在Hadoop中做Hive、Pig和MapReduce的持久化数据格式

总结

序列化 是将对象转化为字节流的过程,用于存储或传输。

反序列化 是将字节流转回对象的过程,以便在接收端处理。

在 Netty 中,序列化和反序列化通过编码器和解码器来实现,支持多种序列化框架,包括 Java 原生序列化、JSON、Protobuf、 Thrift、 Avro 。

选择适合的序列化框架和实现方法可以优化网络通信的性能和效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2077028.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ssrf漏洞之——漏洞复现

漏洞介绍 SSRF漏洞:SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由恶意访问者构造url,由服务端对此url发起请求的一个安全漏洞。 漏洞原理 SSRF 形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,并且没有对目…

Autosar(Davinci) --- 创建一个Implementation Data Types

前言 这里我们讲一下如何创建一个Implementation Data Types(IDT) 一、什么是IDT 二、如何创建一个IDT 鼠标右键【Implementation Data Types】,选择【new Type Reference...】 起一个名字【IdtDoorState】,Data Types选择【boolean】,这里…

RFID光触发标签应用于制造业供应链管理的应用与探索

制造业作为国民经济的支柱产业,其供应链管理的复杂性和重要性日益凸显,在全球化竞争的背景下,企业需要更高效、更精准、更智能的供应链解决方案来满足市场需求,提高客户满意度,降低运营成本,RFID光触发标签…

【mysql】mysql的卸载和安装

mysql的卸载 mysql是否安装: 首先我们先来看看mysql是否安装: 快捷键winR输入cmd,进入命令输入框 输入mysql --version 查看mysql的版本 如果出现了mysql的版本就说明你已经安装了 系统用户root -p就是输入密码所以代码如下 mysql -ur…

AI大模型编写多线程并发框架(六十一):从零开始搭建框架

系列文章目录 文章目录 系列文章目录前言一、项目背景二、第一轮对话-让AI大模型理解我们的诉求二、第二轮对话-优化任务处理方法和结果处理方法三、参考文章 前言 在这个充满技术创新的时代,AI大模型正成为开发者们的新宠。它们可以帮助我们完成从简单的问答到复杂…

模拟实现STL中的unordered_map和unordered_set

目录 1.unordered_map和unordered_set简介 2.unordered_map和unordered_set设计图 3.迭代器的设计 4.哈希表的设计 5.my_unordered_map和my_unordered_set代码 1.unordered_map和unordered_set简介 unordered_map和unordered_set的使用非常类似于map和set,两…

【Linux】日志函数

欢迎来到 破晓的历程的 博客 ⛺️不负时光,不负己✈️ 文章目录 引言日志内容日志等级日志函数的编写函数原型参数说明功能描述使用场景示例代码 引言 日志在程序设计中扮演着至关重要的角色,它不仅是程序运行情况的记录者,还是问题诊断、性…

【机器学习】智驭未来:机器学习如何重塑现代城市管理新生态

📝个人主页🌹:Eternity._ 🌹🌹期待您的关注 🌹🌹 ❀目录 🔍1. 引言:迈向智能城市的新时代📒2. 智驭交通:机器学习在智能交通管理中的应用&#x1…

仿Muduo库实现高并发服务器——LoopThreadPool模块

这个模块需要具备那些基础知识。 线程创建相关操作,锁,条件变量。 设置线程数量: _thread_count 是线程池中,记录线程数量的成员。 创建线程池: 上图就是线程池的创建,将线程与EventLoop对象 通过数组下…

关于嘉立创eda中同一个项目下多个原理图是否独立

嘉立创项目底下,如果你新建了多张原理图,如下 我发现,多张原理图是互相连接的,所以命名是不能重复的 多页原理图 | 嘉立创EDA标准版用户指南https://docs.lceda.cn/cn/Schematic/Multi-Sheet/index.html 上面是嘉立创原文介绍 综…

豆瓣评分7.9!世界级讲师耗时5年整理出的Python学习手册!

Python是一门流行的开源编程语言,广泛用于各个领域的独立程序与脚本化应用中。它不仅免费、可移植、功能强大,同时相对简单,而且使用起来充满乐趣。从软件业界的任意一角到来的程序员,都会发现Python着眼于开发者的生产效率以及软…

编程仙尊——深入理解指针(2)

目录 4.const修饰指针 4.1const修饰变量 5.指针运算 5.1指针-整数 5.2指针-指针 5.3指针的关系运算 6.assert断言 4.const修饰指针 4.1const修饰变量 在编程中,为了防止代码在运行过程中变量的内容意外改变,可以使用const函数,对变量…

介绍python的回归模型原理知识

一.回归 1.什么是回归 回归(Regression)最早是英国生物统计学家高尔顿和他的学生皮尔逊在研究父母和子女的身高遗传特性时提出的。1855年,他们在《遗传的身高向平均数方向的回归》中这样描述“子女的身高趋向于高于父母的身高的平均值&…

Linux云计算 |【第二阶段】SHELL-DAY2

主要内容: 条件测试(字符串比较、整数比较、文件状态)、IF选择结构(单分支、双分支、多分支)、For循环结构、While循环结构 一、表达式比较评估 test 命令是 Unix 和 Linux 系统中用于评估条件表达式的命令。它通常用…

小乌龟运动控制-1 小乌龟划圆圈

目录 第一章 小乌龟划圆圈 第二章 小乌龟走方形 文章目录 目录前言一、准备工作步骤一:创建ROS工作空间步骤二:创建ROS包和节点步骤三:编写Python代码步骤四:运行ROS节点总结 前言 本教程将教会你如何使用Python编写ROS小海龟节…

【SpringCloud】(一文通)优雅实现远程调用-OpenFeign

目 录 一. RestTemplate存在问题二. OpenFeign介绍三. 快速上手3.1 引入依赖3.2 添加注解3.3 编写 OpenFeign 的客户端3.4 远程调用3.5 测试 四. OpenFeign 参数传递4.1 传递单个参数4.2 传递多个参数4.3 传递对象4.4 传递JSON 五. 最佳实践5.1 Feign 继承方式5.1.1 创建⼀个Mo…

马克思发生器有什么用_马克思发生器工作原理

马克思发生器(Marx Generator)是一种电气装置,用于产生高压脉冲电压。它由多个电容器组成,这些电容器依次连接在一系列开关之后。首先,每个电容器被并联充电至较低的电压。然后,这些电容器被开关依次串联&a…

C++过生日(我给我自己做的生日礼物)

🚀欢迎互三👉:程序猿方梓燚 💎💎 🚀关注博主,后期持续更新系列文章 🚀如果有错误感谢请大家批评指出,及时修改 🚀感谢大家点赞👍收藏⭐评论✍ 引言…

电源自动测试系统:测试柜的组成与功能

为了提高电源测试的效率和安全性,电源自动化测试柜是电源ATE自动测试系统的重要设备,不仅对示波器、万用表等测试仪器起保护作用,更是在测试过程中降低了安全风险,方便了电源产品的自动化测试。 电源自动测试系统机柜 电源自动化测…

C++初学(15补充)

15.1、嵌套循环和二维数组 下面讨论如何使用嵌套for循环来处理二维数组。到目前为止,我们一直学的是一维数组,因为每一个数组都可以看作是一行数据。二维数组更像是一个表格——既有数据行也有数据列。C并没有提供二维数组类型,但是用户可以…