浅谈netty

感觉这是一个避不开得话题。干不过就加入。磨就完事了。

 

Netty 是一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。

 

JDK 原生也有一套网络应用程序 API,但是存在一系列问题,主要如下:

  • NIO 的类库和 API 繁杂,使用麻烦。你需要熟练掌握 Selector、ServerSocketChannel、SocketChannel、ByteBuffer 等。
  • 需要具备其他的额外技能做铺垫。例如熟悉 Java 多线程编程,因为 NIO 编程涉及到 Reactor 模式,你必须对多线程和网路编程非常熟悉,才能编写出高质量的 NIO 程序。
  • 可靠性能力补齐,开发工作量和难度都非常大。例如客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常码流的处理等等。 NIO 编程的特点是功能开发相对容易,但是可靠性能力补齐工作量和难度都非常大。
  • JDK NIO 的 Bug。例如臭名昭著的 Epoll Bug,它会导致 Selector 空轮询,最终导致 CPU 100%。 官方声称在 JDK 1.6 版本的 update 18 修复了该问题,但是直到 JDK 1.7 版本该问题仍旧存在,只不过该 Bug 发生概率降低了一些而已,它并没有被根本解决。

 

 

Netty 的特点

Netty 对 JDK 自带的 NIO 的 API 进行封装,解决上述问题,主要特点有:

  • 设计优雅,适用于各种传输类型的统一 API 阻塞和非阻塞 Socket;基于灵活且可扩展的事件模型,可以清晰地分离关注点;高度可定制的线程模型 - 单线程,一个或多个线程池;真正的无连接数据报套接字支持(自 3.1 起)。
  • 使用方便,详细记录的 Javadoc,用户指南和示例;没有其他依赖项,JDK 5(Netty 3.x)或 6(Netty 4.x)就足够了。
  • 高性能,吞吐量更高,延迟更低;减少资源消耗;最小化不必要的内存复制。
  • 安全,完整的 SSL/TLS 和 StartTLS 支持。
  • 社区活跃,不断更新,社区活跃,版本迭代周期短,发现的 Bug 可以被及时修复,同时,更多的新功能会被加入。

 

 

Netty 常见的使用场景如下:

  • 互联网行业。在分布式系统中,各个节点之间需要远程服务调用,高性能的 RPC 框架必不可少,Netty 作为异步高性能的通信框架,往往作为基础通信组件被这些 RPC 框架使用。 典型的应用有:阿里分布式服务框架 Dubbo 的 RPC 框架使用 Dubbo 协议进行节点间通信,Dubbo 协议默认使用 Netty 作为基础通信组件,用于实现各进程节点之间的内部通信。
  • 游戏行业。无论是手游服务端还是大型的网络游戏,Java 语言得到了越来越广泛的应用。Netty 作为高性能的基础通信组件,它本身提供了 TCP/UDP 和 HTTP 协议栈。 非常方便定制和开发私有协议栈,账号登录服务器,地图服务器之间可以方便的通过 Netty 进行高性能的通信。
  • 大数据领域。经典的 Hadoop 的高性能通信和序列化组件 Avro 的 RPC 框架,默认采用 Netty 进行跨界点通信,它的 Netty Service 基于 Netty 框架二次封装实现。

 

 netty的线程模型?

netty的线程模型是基于reactor模式的一种实现,所以了我们先来了解一下reactor的三种线程模型:

Reactor单线程模型

Reactor多线程模型

Reactor主从多线程模型(默认)

 

 

 netty的select,poll,epoll区别?

 

 

 

 

 

netty多路复用怎么实现的?

目前支持I/O多路复用的系统调用有select、pselect、poll、epoll.

select:采用轮询的方式扫描文件描述符,全部扫描,随着文件描述符FD数量增多而性能下降,,每次调用 select(),需要把 fd 集合从用户态拷贝到内核态,并进行遍历(消息传递都是从内核到用户空间),最大的缺陷就是单个进程打开的FD有限制,默认是1024   (可修改宏定义,但是效率仍然慢)

epoll:处理多个描述符也是使用轮询的方式,根据描述符的状态进行处理,一样需要把 fd 集合从用户态拷贝到内核态,并进行遍历。poll没有最大文件描述符限制(使用链表的方式存储fd)

epoll:基本原理:在2.6内核中提出的,对比select和poll,epoll更加灵活,没有描述符限制,用户态拷贝到内核态只需要一次使用事件通知,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用callback的回调机制来激活对应的fd

 

 

netty性能高的原因?

1、网络模型

多路复用IO,采用一个线程处理连接请求,多个线程处理IO请求,他比BIO能处理更多请求,数据请求和数据处理都是异步,底层采用了linux的select、poll、epoll

2、零拷贝

主要使用了bytebuffer,使用了堆外内存

3、内存池

采用了内存池技术,避免了频繁申请内存的消耗

4、锁

netty采用了更细粒度的锁,注意锁的对象本身大小,减少空间占用,注意锁的速度,提高速度,不同场景选择不同的并发类 ,因需而边,衡量好锁的价值,能不用则不用

5  高效的 Reactor线程模型

6、高性能序列化协议,支持protobuf等高性能序列化协议

 

 

什么是零拷贝?

零拷贝(英语: Zero-copy) 技术是指计算机执行操作时,CPU不需要先将数据从某处内存复制到另一个特定区域。这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽。

➢零拷贝技术可以减少数据拷贝和共享总线操作的次数,消除传输数据在存储器之间不必要的中间拷贝次数,从而有效地提高数据传输效率

 

 

零拷贝怎么实现的?

Netty 的零拷贝主要包含三个方面:

(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 方式导致的内存拷贝问题。

 

在下面这些组件、框架中有用到零拷贝 (Zero-Copy):

Kafka
Netty
rocketmq
nginx
apache

 

posted @   雪域飞魂  阅读(159)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示