【NIO系列】——之Netty
这是NIO系列的第四篇,欢迎继续关注:
- 【NIO系列】——之TCP探秘
- 【NIO系列】——之IO模型
- 【NIO系列】——之Reactor模型
如果你看过前面三篇文章,我们从最低层来分解NIO底层原理和使用方式,帮忙我们理解了NIO是什么,解决了什么问题,以及又有那些不足。
原则上NIO的出现,已经提升和加快了网络IO的处理方式,但它只能帮忙我们解决了IO层次的读写问题,在软件层次上我们需要更好的编程架构模型,来解决扩展性以及高并发的问题。Netty正是用来解决这些问题的,这一篇我们将详细介绍Netty的知识点。
一、netty是什么
1、是什么
我们采用官方的话来说:
Netty是一个高性能、异步事件驱动的网络应用框架。 基于Netty,可以快速的开发和部署高性能、 高可用的网络服务端和客户端应用。
简单来说,它是一个网络应用框架,帮你解决面向网络开发中的三个问题:
面向网络IO的读写,如TCP的socket连接
应用层协议编解码,如HTTP协议
高并发架构
那么他有哪些优点?
Fast —性能强悍,高并发,低延迟
Easy —高扩展,API使用简单,开发门槛低
Non-blocking — 无阻塞,支持NIO
2、有何不同
对于我们用惯了web容器的人来说,第一个疑惑就是netty究竟能干什么,为何要用它。既然Netty是一个网络应用框架,这些明明tomcat也能帮我们解决了,为何还要用Netty?
netty和tomcat的不同,主要在以下几点:
tomcat是一个「HTTP Server」,更准确的说是一个「Servlet/JSP」应用的容器,它主要解决的是 HTTP 协议层面的传输和访问。
HTTP是一种应用层协议,应用层的协议除了HTTP以外,还有面向邮局协议的POP和IMAP,以及FTP、LDAP、SSH、TLS/SSL等其他协议。
Netty 不仅可以支持HTTP,还可以支持FTP、LDAP、SSH、TLS/SSL等应用层多数的协议,另外还支持自定义的应用层协议,只要你有这方面的需求,它足够灵活。
Netty 虽然按归类上算属于OSI的第七层【应用层】,但它的存在是帮你支持第三层【传输层】的问题,比如面向TCP,面向UDP,以及SCTP网络协议的开发,它都能很好的支持。所以他可以称为一个通信组件。
原则上,Tomcat的网络通信组件也可以采用Netty,但servlet3.0之前完全是同步阻塞模型,tomcat要遵循servlet规范所以不能最大发挥NIO的特性,而Netty不用遵循servlet规范,可以最大化发挥NIO的特性,性能更高一些。
二、为何要用Netty
Netty的三大特性(fast,easy,no-blocking)可以详细分解为以下特性:
支持NIO,异步编程
性能强悍,高并发,低延迟,更少的资源占用和内存使用率带来更快的性能支撑,NIO领域最强
成熟、稳定,你想到的一切tcp 问题,都已经解决,特别是NIO bug,以及完美解决了。
不仅仅支持http,支持多种应用协议和网络协议,如TCP/UDP/UDT/SCTP/FTP/SMTP等。
功能强大,预制了多种编解码处理器,支持多种主流应用协议
API使用简单,开发门槛低
1.Fast
为何快,可以参考上篇文章(【NIO系列】——之Reactor模型)介绍的Reactor IO模型。
Netty正是基于NIO实现了这种Reactor模型,Boss线程用来专门处理连接的建立,SubReactor专门用来处理IO的读写以及任务的处理。这种线程模型在充分利用CPU性能的情况下支撑大量的并发连接。
具体效果如何,我们看下测试数据:
以上是在techempower获取的关于webFrame的纯文本响应测试,可以看到netty在响应速度方面,排名第二,虽然近几年高性能的web框架不断的挑战,netty排名有所下降,但依然还能保持前列位置。
以上是在dubbo的官方测试案例中,给定协议序列化TPS对比,可以看到采用netty的dubbo,在tps方面名列前茅。
2.更少的内存使用
Netty因为要面对大量的网络数据包处理,所以会有大量的网络对象创建和销毁,对JVM来说有很大的压力。
Netty主要采用两种方案来缓解JVM的压力:
ByteBufAllocator 对象池。池化ByteBuf实例以提高性能并最小化内存碎片,后者每次调用时都返回一个新的实例。
零拷贝。支持DirectBuffer的使用,通过JVM的本地调用分配内存,这可避免每次调用本地I / O操作之前(或之后)将缓冲区的内容复制到(或从)中间缓冲区。
以下是twitter对应Netty4的使用对象池应用压测:
3.Easy,快速开发
我们知道牵扯到网络上的编程会比较复杂,除了有一堆需要设置的TPC参数以外,还有一堆IO读写的问题要处理,同时为了提高并发能力,还采用多线程,这就又带来了线程安全的问题,往往给开发者带来了很大的挑战和复杂度。
而Netty 正是针对这些难点统一做了简易化的封装,除了让API更加简单易用以外,比如:TCP服务器的配置启动,数据包buffByte的读写等。另外基于事件模式,对网络事件进行串行处理,在保证了高效的同时,又降低了编程的复杂度。
为何串行化执行会提升netty的性能:
串行无锁化设计,在IO线程内部进行串行操作,避免多线程竞争导致的性能下降。
通过调整NIO线程池的线程参数,可以同时启动多个串行化的线程并行运行,这种局部无锁化的串行线程设计相比一个队列-多个工作线程模型性能更优
减少上下文切换,以及状态数据的同步
以下 是ChannelPipeline用来处理网络事件的职责链,负责管理和执行ChannelHandler。网络事件以事件流的形式在ChannelPipeline中流转。支持插拔模式,扩展性也很强。
4.可靠稳定
在网络方面,应用常常要面对复杂的网络环境,比如网络环境差,常会出现一些网络闪断,单通以及网络阻塞等等一系列问题。另外作为基础的通信组件,还需要考虑健壮性的问题,因为一旦出现bug,则会导致依赖的大量业务中断。
Netty 在版本迭代中不断的加入一些可靠性特性来满足用户日益高涨的可靠性与健壮性需求。比如NIO的select空转bug,比如TCP的断线重连,keep-alive检测等问题,Netty已经帮你解决了。
特别是Netty在推出4.0之后,已经被各家大厂采纳为通信组件,这是对其可靠性验证,也是社区对其稳定性的认可。以下是在使用netty的一些公司,更多参考netty.Adopters
三、如何用
上面介绍了这么多Netty如何厉害,到编码阶段不会出现一堆代码来要处理吧。
我们来一个简单的TCPServer来进行示例.
需求:
Client:接收用户输入的内容,并发送给Server,同时收并显示Server返回的内容
Server:监听8088端口,接收并显示Client发送的内容,并给Client相应的回复
代码:
// step 1 设置boss 和 workEventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {// step 2 服务启动辅助类ServerBootstrap b = new ServerBootstrap(); // 设置线程池b.group(bossGroup, workerGroup)// step3 设置channel.channel(NioServerSocketChannel.class) // setp4 设置channel hanlder.childHandler(new ChildChannelHandler())//设置发送和接受缓冲区大小.option(ChannelOption.SO_SNDBUF,256).option(ChannelOption.SO_RCVBUF,256)// 小封包自动连接.option(ChannelOption.TCP_NODELAY,true).childOption(ChannelOption.SO_KEEPALIVE, true).handler(new LoggingHandler(LogLevel.INFO));// step 7 Bind 监听端口.ChannelFuture f = b.bind(PORT).sync(); logger.info("tcp server start success... ");f.channel().closeFuture().sync();} finally {}复制代码
ChildChannelHander 扩展Pipeline的执行策略:
protected void initChannel(SocketChannel channel) throws Exception {ChannelPipeline pipeline = channel.pipeline();pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));pipeline.addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));pipeline.addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));pipeline.addLast(new TcpHelloServerHandler());
}复制代码
通过以上代码,我们大概需要通过7个步骤,就能创建一个TCP的Server服务器了,看似7步较多,其实看代码量来说,已经很少了。
通过以上的执行流程图,我们可以看到:
ServerBootstrap是服务启动(引导)辅助类,采用无参构造器(Builder模式)提供一系统方法用于设置启动相关的参数
EventLoopGroup:Netty的Reactor线程池,负责维护一组EventLoop的调度工作,通常是bossEventLoop用来维护连接,subEventLoop来维护所有已注册的Channel的I/O操作处理用户自定义的Task和定时任务的Task
Channel:对Java原生的NIO类库进行了封装对一般用户而言,不需要关心底层实现细节和工作原理,只需要指定具体使用哪种Channel,用以连接IO设备(socket)的纽带,提供与IO设备异步I/O操作的支持(如读、写、连接和绑定)
ChildChannelHandler,用来配置ChannelPipeline的执行策略。用来扩展的关键接口,用户可以完成大多数的功能定制,如消息编解码、心跳、安全认证、TSL/SSL认证、流量控制等。
四、最后
以上我们通过Netty 是什么、怎么用、为何用三个方面阐述了Netty的优势以及基本的介绍,想必能够对Netty做一个基本的了解。后续我们将对Netty高性能架构,以及多线程高效编程方面,结合源码,会有更多的剖析。我们不仅仅关注源码是如何实现了,还会结合整个架构,来分析设计理念,以及探讨鲁棒性很强的代码的编写方式。若有兴趣,欢迎持续关注。
更多架构知识,欢迎关注我的公众号,大码候(cool_wier)
【NIO系列】——之Netty相关推荐
- Java游戏服务器系列之Netty详解
今天带大家来学习Java游戏服务器的相关知识,文中对Netty作了非常详细的介绍,对正在学习java的小伙伴们有很好的帮助,需要的朋友可以参考下 一.简介 Java的底层API逐渐复杂,而开发者面对的 ...
- 【读后感】Netty 系列之 Netty 高性能之道 - 相比 Mina 如何 ?
[读后感]Netty 系列之 Netty 高性能之道 - 相比 Mina 如何 ? 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商 ...
- Netty系列之Netty百万级推送服务设计要点
原文来自于:李林峰 https://www.infoq.cn/article/netty-million-level-push-service-design-points/ 1. 背景 1.1. 话题 ...
- 踏莎行·术 - NIO系列1:框架拆解
最近一年用NIO写了不少网络程序,也研究了一些开源NIO网络框架netty.mina等,总结了一下NIO的架构特点. 无论是netty还是mina它们都在java原生NIO的基础上进行了完善的封装,虽 ...
- Java NIO系列教程(十二) Java NIO与IO
原文地址:http://tutorials.jenkov.com/java-nio/nio-vs-io.html 作者:Jakob Jenkov 译者:郭蕾 校对:方腾飞 当学习了Java ...
- Java NIO系列教程(三) Buffer
2019独角兽企业重金招聘Python工程师标准>>> Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的. 缓冲区本 ...
- Java NIO系列教程(五) 通道之间的数据传输
在Java NIO中,如果两个通道中有一个是FileChannel,那你可以直接将数据从一个channel(译者注:channel中文常译作通道)传输到另外一个channel. transferFro ...
- Java NIO系列教程(四) Scatter/Gather
转载自 Java NIO系列教程(四) Scatter/Gather 译文地址 作者:Jakob Jenkov 译者:郭蕾 Java NIO开始支持scatter/gather,scatte ...
- Java NIO系列教程(十) Java NIO DatagramChannel
转载自 Java NIO系列教程(十) Java NIO DatagramChannel 译文链接 作者:Jakob Jenkov 译者:郑玉婷 校对:丁一 Java NIO中的 ...
- Java NIO系列教程(十一) Pipe
转载自 Java NIO系列教程(十一) Pipe 原文链接 作者:Jakob Jenkov 译者:黄忠 校对:丁一 Java NIO 管道是2个线程之间的单向数据连接. ...
最新文章
- 学习Html之后总结的超全的思维导图!
- struts2添加需要的jar包
- nchar,char,varchar与nvarchar区别
- VTK:图片之ImageEllipsoidSource
- html块状元素高度,CSS:如何计算块元素的高度?
- 如何脚踏实地构建Java Agent
- 飞鸽传书的设计应当具有“完整性”
- Node.js 和 Python之间如何进行选择?教你一招搞定
- dedecms 标签使用集锦
- python计算排队时间_python计算排队时间_Python(pdb)-排队执行命令
- python图像加坐标_Python使用matplotlib模块绘制图像并设置标题与坐标轴等信息示例...
- Python全栈开发之2、运算符与基本数据结构
- 解决php中json_decode的异常JSON_ERROR_CTRL_CHAR
- hector与gmapping总结
- C机顶盒开发实战常量定义方式、结构定义方式(可理解为对象Model)
- 如何用Python做好友管理系统
- mybatis实战之拦截器
- 驾照考试之科目二(深圳仙田版)
- JS脚本实现模拟按钮点击:批量抓取百度推广中的关键词建议
- 使用C语言教你轻松学会Cantor表
热门文章
- 关于JAVA调用oracle存储过程
- 第十二章 演员评论家(Actor-Critic)-强化学习理论学习与代码实现(强化学习导论第二版)
- Aminer学术社交网络数据知识图谱构建(三元组与嵌入)
- 智能优化算法:生物地理学优化算法-附代码
- Python-GDAL读取遥感影像直方图统计
- HTML学习总结(1)——HTML基本介绍
- 寿光农商行计算机机房,寿光农村商业银行:新系统上线前奏——培训
- android andbase,andbase
- android 子线程的网络请求为什么还会造成界面卡顿_京东数科mPaaS:深度解读京东金融App(Android)的秒开优化实践...
- Android的JNI【实战教程】3⃣️--Java调用C代码