搭稳Netty开发的地基,用漫画帮你分清同步异步阻塞非阻塞

简介: NettyNetty是一款非常优秀的网络编程框架,是对NIO的二次封装,本文将重点剖析Netty客户端的启动流程,深入底层了解如何使用NIO编程客户端。Linux网络编程5种IO模型根据UNIX网络编程对于IO模型的分类,UNIX提供了5种IO模型,分别是 阻塞IO 、 非阻塞IO、 IO复用 、 信号驱动IO 、 异步IO 。这几种IO模型在《UNIX网络编程》中有详解,这里作者只简单介绍,帮助大家回忆一下这几种模型。对于Linux来说,所有的操作都是基于文件的,也就是我们非常熟悉的fd,在缺省的情况下,基于文件的操作都是 阻塞的 。下面就通过系统调用 recvfrom 来回顾下

Netty

Netty是一款非常优秀的网络编程框架,是对NIO的二次封装,本文将重点剖析Netty客户端的启动流程,深入底层了解如何使用NIO编程客户端。

Linux网络编程5种IO模型

根据UNIX网络编程对于IO模型的分类,UNIX提供了5种IO模型,分别是 阻塞IO非阻塞IOIO复用信号驱动IO异步IO 。这几种IO模型在《UNIX网络编程》中有详解,这里作者只简单介绍,帮助大家回忆一下这几种模型。

对于Linux来说,所有的操作都是基于文件的,也就是我们非常熟悉的fd,在缺省的情况下,基于文件的操作都是 阻塞的 。下面就通过系统调用 recvfrom 来回顾下这五种模型。模型的图示来源于《Netty权威指南》下面不再说明。

系统调用 recvfrom 直到有数据到达并且从内核空间copy到用户空间才返回,这期间 recvfrom调用者一直等待,这就是阻塞IO。

非阻塞IO

应用进程反复调用 recvfrom 询问操作系统内核数据是否准备好,相对于阻塞来说,你可以理解为非阻塞自主能力变强。从图中可以看出数据没有准备好的时候内核返回 EWOULDBLOCK

Linux给我们提供的IO复用相关的函数有 selectpollepoll 这几个函数的优缺点这里就不做详述了,想要再深入了解的同学可以看下我以前的这篇文章: epoll详解:从底层了解IO复用 。

信号驱动IO

应用进程建立一个 SIGIO信号 处理程序,当内核数据准备好的时候,会产生一个 SIGIO信号 ,处理程序收到这个信号并通知进程调用 recvfrom

应用程序执行系统调用,告知内核某个操作,并让内核在整个操作完成后(包括将数据从内核复制到应用缓冲区)通知应用进程。这种模式与信号驱动模式的主要区别在于:信号驱动IO由内核通知我们何时可以开始IO操作。异步驱动IO由内核通知我们IO操作是否完成。

用漫画帮你分清同步异步阻塞非阻塞

说到 同步异步阻塞非阻塞 很多人分不清他们之间的区别,每次听到这几个词语的时候就头大。更别说他们的组合 同步阻塞同步非阻塞异步阻塞异步非阻塞 了。针对这几个大家非常容易混淆的词语,我画了一幅漫画帮助大家理解。欢迎大家来吐槽我的第一个漫画作品《洗衣服的故事》。

你看到这四个词语的时候肯定以为是说的同一件事,描述的是同一个对象,这种理解是错误的。我们可以把 同步、异步 看做一组, 阻塞和非阻塞 看成一组。这两者的主要区别就是:前者是" 消息通知机制 ",后者是“ 等到消息通知时的状态 ”。

这样说你可能还是没有理解,结合上面的漫画情景中"消息通知机制"就是洗衣机,“等待消息通知时的状态"就是人。拿"异步非阻塞"举例,洗衣机洗完衣服会发出"滴滴"声通知人已经完成了"洗衣服"这个任务,这就是"消息通知机制”,这个过程中人不必傻等着洗衣机"洗衣服"这个任务的结果,可以干其他的事情“浇花”,听到洗衣机的"滴滴"声之后可以去"晾衣服"。这就是一种"等待消息通知时的状态"。

从BIO到AIO

BIO通信模型

BIO通信模型也叫 一请求一应答 模型。顾名思义,服务器每接收到一个请求就会生成一个线程来处理这个请求。

这种模式最大的问题是缺乏弹性伸缩能力。这种模式接收一个请求就开启一个线程去处理。众所周知,线程资源对于JVM虚拟机是极其宝贵的,线程数过度膨胀的时候,系统性能会急剧下降,并发很大的情况下很容易会导致资源耗尽而出现堆栈溢出,进而出现宕机或者僵死、服务器崩溃,无法对外服务。上面图示中Client5就是资源耗尽时服务器无法提供服务的场景,用户看到的将是异常或者超时。

为异步IO模型

用过线程池的同学都知道线程池的好处是我们可以指定 核心线程数最大线程数线程池队列大小 并且可以设置 拒绝策略 。所以这种模式相比于阻塞IO来说线程的创建,服务的范围是 可控的 。无论多少个客户端并发,都不会导致服务器资源的耗尽和宕机。

NIO编程

NIO是 Non-block I/O(非阻塞IO) 的简称。使用IO复用编写的服务器和客户端就是NIO编程的很好的示例。我们设置了读写都是非阻塞之后,当没有可读或者可写的数据的时候,线程不同步等待,会直接返回。想要再深入了解的同学可以看下我以前的这篇文章: epoll详解:从底层了解IO复用 。

AIO编程

NIO 2.0引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现。

异步通道获取获取操作结果方式:

1.使用 java.util.concurrent.Future类 表示异步操作的结果;

2.在执行异步操作的时候传入一个 java.nio.channels

操作完成后胡回调 CompletionHandler 接口的实现类。

NIO 2.0的异步套接字通道是真正的异步非阻塞I/O,对应于UNIX网络编程中的事件驱动I/O。

为什么选择Netty

不选择Java原生NIO编程的原因

以下内容引用自《Netty权威指南》:

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

为什么选择Netty

Netty是业界最流行的NIO框架之一, 它的健壮性、功能、性能、可定制性和可扩展性在同类框架中都是首屈一指的, 它已经得到成百上千的商用项目验证, 例如Hadoop的RPC框架Avro就使用了Netty作为底层通信框架, 其他还有业界主流的RPC框架, 也使用Netty来构建高性能的异步通信能力。

通过对Netty的分析,我们将它的优点总结如下。

  • API使用简单, 开发门槛低;
  • 功能强大,预置了多种编解码功能,支持多种主流协议;
  • 定制能力强, 可以通过 ChannelHandler 对通信框架进行灵活地扩展;
  • 性能高, 通过与其他业界主流的NIO框架对比,Netty的综合性能最优;
  • 成熟、稳定,Netty修复了已经发现的所有 JDK NIO BUG , 业务开发人员不需要再为NIO的BUG而烦恼;
  • 社区活跃, 版本迭代周期短, 发现的BUG可以被及时修复,同时, 更多的新功能会加入;
  • 经历了大规模的商业应用考验, 质量得到验证。Netty在互联网、大数据、网络游戏、企业应用、电信软件等众多行业已经得到了成功商用,证明它已经完全能够满足不同行业的商业应用了。
    正是因为这些优点,Netty 逐渐成为了 Java NIO 编程的首选框架。

通过以上内容帮助大家回忆一下Linux网络编程中的IO模型,搞清楚同步异步阻塞非阻塞的概念,了解了BIO到NIO的区别和联系。最后我们知道了众多的NIO框架中,为什么要选择Netty。这些知识也是我们后续进行网络编程和Netty开发的基础。

以上就是有关Netty的有关内容,希望可以对大家学习Netty有帮助,喜欢的小伙伴可以帮LZ进行转发+关注,也会不定时更新干货!感谢大家!

相关文章
|
8月前
|
Java Unix Linux
【Netty技术专题】「原理分析系列」Netty强大特性之Native transports扩展开发实战
当涉及到网络通信和高性能的Java应用程序时,Netty是一个强大的框架。它提供了许多功能和组件,其中之一是JNI传输。JNI传输是Netty的一个特性,它为特定平台提供了高效的网络传输。 在本文中,我们将深入探讨Netty提供的特定平台的JNI传输功能,分析其优势和适用场景。我们将介绍每个特定平台的JNI传输,并讨论其性能、可靠性和可扩展性。通过了解这些特定平台的JNI传输,您将能够更好地选择和配置适合您应用程序需求的网络传输方式,以实现最佳的性能和可靠性。
153 7
【Netty技术专题】「原理分析系列」Netty强大特性之Native transports扩展开发实战
|
5月前
|
API 开发者
Netty运行原理问题之Netty实现低开发门槛的问题如何解决
Netty运行原理问题之Netty实现低开发门槛的问题如何解决
|
7月前
|
监控 网络协议 Java
Java一分钟之-Netty:高性能异步网络库
【6月更文挑战第11天】Netty是Java的高性能异步网络框架,基于NIO,以其高吞吐量、低延迟、灵活性和安全性受到青睐。常见问题包括内存泄漏、ChannelHandler滥用和异常处理不当。要规避这些问题,需正确释放ByteBuf,精简ChannelPipeline,妥善处理异常,并深入理解Netty原理。通过代码审查、遵循最佳实践和监控日志,可提升代码质量和性能。掌握Netty,打造高效网络服务。
96 2
|
6月前
|
安全 NoSQL Java
网络安全-----Redis12的Java客户端----客户端对比12,Jedis介绍,使用简单安全性不足,lettuce(官方默认)是基于Netty,支持同步,异步和响应式,并且线程是安全的,支持R
网络安全-----Redis12的Java客户端----客户端对比12,Jedis介绍,使用简单安全性不足,lettuce(官方默认)是基于Netty,支持同步,异步和响应式,并且线程是安全的,支持R
|
8月前
|
前端开发 网络协议
启动异步之旅:探索Netty中Bootstrap的神奇世界
启动异步之旅:探索Netty中Bootstrap的神奇世界
48 0
|
8月前
|
前端开发 网络协议 Java
Netty入门指南:从零开始的异步网络通信
Netty入门指南:从零开始的异步网络通信
197 0
|
8月前
|
前端开发 Java API
构建异步高并发服务器:Netty与Spring Boot的完美结合
构建异步高并发服务器:Netty与Spring Boot的完美结合
|
8月前
Netty Review - 借助SimpleTalkRoom初体验异步网络编程的魅力
Netty Review - 借助SimpleTalkRoom初体验异步网络编程的魅力
88 0
|
存储 缓存 NoSQL
跟着源码学IM(十一):一套基于Netty的分布式高可用IM详细设计与实现(有源码)
本文将要分享的是如何从零实现一套基于Netty框架的分布式高可用IM系统,它将支持长连接网关管理、单聊、群聊、聊天记录查询、离线消息存储、消息推送、心跳、分布式唯一ID、红包、消息同步等功能,并且还支持集群部署。
13538 1
|
8月前
|
消息中间件 Oracle Dubbo
Netty 源码共读(一)如何阅读JDK下sun包的源码
Netty 源码共读(一)如何阅读JDK下sun包的源码
152 1